From b51fc0bc52762270060ed1183c740ebc30a552c8 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini Date: Tue, 23 Jun 2026 15:45:53 -0400 Subject: [PATCH] Fix #3 - Code base cleanup and prepare for v2 Signed-off-by: Ricardo Zanini --- .dockerignore | 3 + .env | 26 + .github/workflows/ci.yaml | 44 + .github/workflows/cli-build.yaml | 112 - .github/workflows/cli-e2e.yaml | 88 - .github/workflows/e2e-minimal.yaml | 158 - .github/workflows/e2e.yaml | 186 - .github/workflows/pr-checks.yaml | 130 - .gitignore | 47 +- .golangci.yml | 55 + .idea/runConfigurations/Build_Manager.xml | 12 + .idea/runConfigurations/Make_Build.xml | 8 + .idea/runConfigurations/Make_Test.xml | 8 + CLAUDE.md | 41 + Dockerfile | 33 + E2E_SETUP.md | 220 - MIGRATION.md | 65 - Makefile | 502 +- PROJECT | 51 +- README.md | 190 +- api/Makefile | 20 - api/go.mod | 75 - api/go.sum | 221 - api/metadata/annotations.go | 115 - api/metadata/annotations_test.go | 62 - api/status_types.go | 44 - api/v1/groupversion_info.go | 36 + api/v1/logicflowdefinition_types.go | 64 + api/v1/logicflowruntime_types.go | 64 + api/v1/logicflowservice_types.go | 64 + api/v1/logicplatform_types.go | 64 + api/v1/zz_generated.deepcopy.go | 381 + api/v1alpha08/conversion.go | 180 - api/v1alpha08/conversion_test.go | 154 - api/v1alpha08/groupversion_info.go | 44 - api/v1alpha08/podtemplate_types.go | 574 - api/v1alpha08/sonataflow_persistence_types.go | 121 - api/v1alpha08/sonataflow_types.go | 348 - api/v1alpha08/sonataflowbuild_types.go | 170 - .../sonataflowclusterplatform_types.go | 117 - ...sonataflowclusterplatform_types_support.go | 34 - .../sonataflowplatform_build_types.go | 107 - .../sonataflowplatform_devmode_types.go | 26 - .../sonataflowplatform_property_types.go | 56 - .../sonataflowplatform_services_types.go | 69 - api/v1alpha08/sonataflowplatform_types.go | 259 - .../sonataflowplatform_types_support.go | 34 - api/v1alpha08/testdata/camel.sw.json | 34 - api/v1alpha08/testdata/foreach.sw.json | 49 - api/v1alpha08/testdata/invalid.sw.json | 6 - api/v1alpha08/testdata/sonataflow-camel.yaml | 44 - .../testdata/sonataflow-foreach.yaml | 53 - .../testdata/sonataflow-invalid.yaml | 27 - api/v1alpha08/zz_generated.deepcopy.go | 1559 - api/zz_generated.deepcopy.go | 30 +- bundle/README.md | 28 - bundle/metadata/annotations.yaml | 34 - bundle/tests/scorecard/config.yaml | 84 - cli/DEPRECATED.md | 41 + cli/go.mod | 4 - cli/go.sum | 3 + cmd/main.go | 325 +- config/crd/bases/.gitkeep | 0 ...c.kubesmarts.org_logicflowdefinitions.yaml | 55 + ...ogic.kubesmarts.org_logicflowruntimes.yaml | 54 + ...ogic.kubesmarts.org_logicflowservices.yaml | 54 + .../logic.kubesmarts.org_logicplatforms.yaml | 54 + config/crd/kustomization.yaml | 48 +- config/crd/kustomizeconfig.yaml | 41 +- .../cainjection_in_sonataflowbuilds.yaml | 24 - ...jection_in_sonataflowclusterplatforms.yaml | 24 - .../cainjection_in_sonataflowplatforms.yaml | 24 - .../patches/cainjection_in_sonataflows.yaml | 24 - .../patches/webhook_in_sonataflowbuilds.yaml | 33 - ...webhook_in_sonataflowclusterplatforms.yaml | 33 - .../webhook_in_sonataflowplatforms.yaml | 33 - .../crd/patches/webhook_in_sonataflows.yaml | 33 - .../default/cert_metrics_manager_patch.yaml | 30 + config/default/controllers_config_patch.yaml | 35 - config/default/kustomization.yaml | 261 +- config/default/manager_auth_proxy_patch.yaml | 67 - config/default/manager_config_patch.yaml | 37 - config/default/manager_metrics_patch.yaml | 4 + config/default/metrics_service.yaml | 18 + .../manager/SonataFlow-Builder.containerfile | 50 - config/manager/controller_manager_config.yaml | 28 - config/manager/controllers_cfg.yaml | 64 - config/manager/kustomization.yaml | 49 - config/manager/manager.yaml | 124 +- config/manager/manager_env_patch.yaml | 45 - ...taflow-operator.clusterserviceversion.yaml | 303 - config/manifests/kustomization.yaml | 29 +- .../network-policy/allow-metrics-traffic.yaml | 27 + config/network-policy/kustomization.yaml | 2 + config/prometheus/kustomization.yaml | 28 +- config/prometheus/monitor.yaml | 31 +- config/prometheus/monitor_tls_patch.yaml | 19 + .../rbac/auth_proxy_client_clusterrole.yaml | 26 - config/rbac/auth_proxy_role.yaml | 34 - config/rbac/auth_proxy_role_binding.yaml | 29 - config/rbac/auth_proxy_service.yaml | 30 - config/rbac/builder_role.yaml | 85 - config/rbac/builder_role_binding.yaml | 29 - config/rbac/knative_role.yaml | 69 - config/rbac/knative_role_binding.yaml | 30 - config/rbac/kustomization.yaml | 80 +- config/rbac/leader_election_role.yaml | 82 +- config/rbac/leader_election_role_binding.yaml | 26 +- .../rbac/logicflowdefinition_admin_role.yaml | 27 + .../rbac/logicflowdefinition_editor_role.yaml | 33 + .../rbac/logicflowdefinition_viewer_role.yaml | 29 + config/rbac/logicflowruntime_admin_role.yaml | 27 + config/rbac/logicflowruntime_editor_role.yaml | 33 + config/rbac/logicflowruntime_viewer_role.yaml | 29 + config/rbac/logicflowservice_admin_role.yaml | 27 + config/rbac/logicflowservice_editor_role.yaml | 33 + config/rbac/logicflowservice_viewer_role.yaml | 29 + config/rbac/logicplatform_admin_role.yaml | 27 + config/rbac/logicplatform_editor_role.yaml | 33 + config/rbac/logicplatform_viewer_role.yaml | 29 + config/rbac/metrics_auth_role.yaml | 17 + config/rbac/metrics_auth_role_binding.yaml | 12 + config/rbac/metrics_reader_role.yaml | 9 + config/rbac/openshift_role.yaml | 113 - config/rbac/openshift_role_binding.yaml | 29 - config/rbac/operator_role_binding_leases.yaml | 29 - config/rbac/operator_role_leases.yaml | 35 - config/rbac/role.yaml | 96 +- config/rbac/role_binding.yaml | 26 +- config/rbac/service_account.yaml | 20 +- config/rbac/service_discovery_role.yaml | 75 - .../rbac/service_discovery_role_binding.yaml | 30 - config/rbac/sonataflow_editor_role.yaml | 41 - config/rbac/sonataflow_viewer_role.yaml | 37 - config/rbac/sonataflowbuild_editor_role.yaml | 41 - config/rbac/sonataflowbuild_viewer_role.yaml | 37 - ...sonataflowclusterplatform_editor_role.yaml | 48 - ...rplatform_viewer_cluster_role_binding.yaml | 30 - ...sonataflowclusterplatform_viewer_role.yaml | 44 - .../rbac/sonataflowplatform_editor_role.yaml | 41 - .../rbac/sonataflowplatform_viewer_role.yaml | 37 - config/samples/kustomization.yaml | 29 +- .../samples/logic_v1_logicflowdefinition.yaml | 9 + config/samples/logic_v1_logicflowruntime.yaml | 9 + config/samples/logic_v1_logicflowservice.yaml | 9 + config/samples/logic_v1_logicplatform.yaml | 9 + .../sonataflow.org_v1alpha08_sonataflow.yaml | 59 - ...vmodeWithConfigMapAndExternalResource.yaml | 87 - ...ataflow.org_v1alpha08_sonataflowbuild.yaml | 23 - ...g_v1alpha08_sonataflowclusterplatform.yaml | 25 - ...flow.org_v1alpha08_sonataflowplatform.yaml | 27 - config/scorecard/bases/config.yaml | 21 +- config/scorecard/kustomization.yaml | 47 +- config/scorecard/patches/basic.config.yaml | 23 +- config/scorecard/patches/olm.config.yaml | 47 +- container-builder/Makefile | 56 - container-builder/README.md | 174 - container-builder/api/build_types.go | 246 - container-builder/api/common_type.go | 43 - container-builder/api/doc.go | 22 - container-builder/api/platform_types.go | 77 - .../api/zz_generated.deepcopy.go | 357 - .../builder/kaniko_docker_integration_test.go | 68 - .../builder/kaniko_integration_test_suite.go | 77 - container-builder/builder/kaniko_vanilla.go | 96 - .../builder/kubernetes/action.go | 49 - .../builder/kubernetes/build_pod.go | 185 - .../builder/kubernetes/builder.go | 235 - .../builder/kubernetes/builder_kaniko.go | 108 - .../builder/kubernetes/builder_kaniko_test.go | 173 - .../builder/kubernetes/builder_test.go | 87 - container-builder/builder/kubernetes/env.go | 68 - container-builder/builder/kubernetes/error.go | 49 - .../builder/kubernetes/initialize_pod.go | 63 - .../builder/kubernetes/kaniko.go | 154 - .../kubernetes/kanikoSecurityContext.go | 39 - .../builder/kubernetes/monitor_pod.go | 283 - container-builder/builder/kubernetes/mount.go | 188 - .../builder/kubernetes/mount_test.go | 178 - .../builder/kubernetes/recovery.go | 102 - .../builder/kubernetes/schedule.go | 56 - .../kubernetes/testdata/greetings.sw.json | 67 - .../kubernetes/testdata/sample.Dockerfile | 47 - container-builder/cleaner/cleaner.go | 27 - .../cleaner/docker_integration_test.go | 67 - .../cleaner/docker_integration_test_suite.go | 63 - .../registry_docker_integration_test.go | 44 - container-builder/client/client.go | 227 - container-builder/client/fastmapper.go | 97 - container-builder/common/docker.go | 234 - container-builder/common/registry.go | 48 - container-builder/common/registry_docker.go | 226 - ...usingKanikowithCacheAndCustomizations.yaml | 32 - .../PlatformBuild_usingKanikowithCache.yaml | 26 - container-builder/examples/app.yaml | 45 - .../dockerfiles/SonataFlow.dockerfile | 48 - container-builder/examples/service.yaml | 39 - .../sources/sonataflowgreetings.sw.json | 67 - container-builder/go.mod | 98 - container-builder/go.sum | 278 - container-builder/hack/boilerplate.go.txt | 18 - container-builder/hack/btrfs_installed_tag.sh | 24 - container-builder/hack/btrfs_tag.sh | 24 - container-builder/main.go | 111 - container-builder/util/log/log.go | 28 - container-builder/util/minikube/registry.go | 68 - container-builder/util/registry/kep_1755.go | 99 - container-builder/util/test/client.go | 156 - container-builder/util/util.go | 38 - docs/CLI_E2E_TODO.md | 136 - docs/CLI_MIGRATION_METADATA.md | 90 - docs/CLI_MIGRATION_PLAN.md | 135 - .../operator-sdk-migration-analysis.md | 234 + env/index.js | 108 - go.mod | 209 +- go.sum | 968 +- go.work | 30 - go.work.sum | 4173 --- hack/addheaders.sh | 27 - hack/boilerplate.go.txt | 28 +- hack/bump-version.sh | 57 - hack/create-kind-cluster-with-registry.sh | 112 - hack/env.sh | 94 - hack/go-path.sh | 22 - hack/goimports.sh | 24 - hack/install-operator-sdk.sh | 92 - hack/license-header.txt | 13 - hack/local/run-e2e-crc.sh | 31 - hack/local/run-e2e.sh | 75 - hack/local/run-operator.sh | 35 - hack/pull-test-images.sh | 53 - hack/setup-cekit.sh | 35 - hack/update_patch_env.py | 119 - images/bundle.yaml | 68 - images/manager.yaml | 57 - .../module.yaml | 31 - .../install.sh | 20 - .../module.yaml | 48 - .../install.sh | 21 - .../module.yaml | 45 - images/requirements.txt | 21 - internal/controller/builder/builder.go | 87 - internal/controller/builder/config.go | 96 - .../controller/builder/containerbuilder.go | 234 - .../builder/kogitoserverlessbuild_manager.go | 141 - .../kogitoserverlessbuild_manager_test.go | 182 - .../controller/builder/openshiftbuilder.go | 300 - .../builder/openshiftbuilder_test.go | 175 - internal/controller/cfg/controllers_cfg.go | 153 - .../controller/cfg/controllers_cfg_test.go | 74 - .../cfg/testdata/controllers-cfg-invalid.yaml | 18 - .../cfg/testdata/controllers-cfg-test.yaml | 36 - internal/controller/clusterplatform/action.go | 50 - .../clusterplatform/clusterplatform.go | 122 - .../controller/clusterplatform/defaults.go | 56 - .../controller/clusterplatform/initialize.go | 123 - internal/controller/const.go | 25 - internal/controller/discovery/discovery.go | 246 - .../discovery/discovery_knative_test.go | 127 - .../discovery/discovery_openshift_test.go | 123 - .../controller/discovery/discovery_test.go | 258 - .../controller/discovery/knative_catalog.go | 136 - .../discovery/kubernetes_catalog.go | 138 - .../discovery/kubernetes_constants.go | 29 - .../controller/discovery/openshift_catalog.go | 132 - internal/controller/discovery/port_utils.go | 94 - .../controller/discovery/port_utils_test.go | 132 - internal/controller/discovery/queries.go | 154 - internal/controller/discovery/queries_test.go | 281 - internal/controller/discovery/test_utils.go | 211 - internal/controller/discovery/uri_parser.go | 242 - .../controller/discovery/uri_parser_test.go | 330 - internal/controller/discovery/uri_utils.go | 116 - .../controller/discovery/uri_utils_test.go | 138 - .../controller/eventing/workflowdef_events.go | 73 - internal/controller/knative/knative.go | 446 - .../logicflowdefinition_controller.go | 63 + .../logicflowdefinition_controller_test.go | 84 + .../controller/logicflowruntime_controller.go | 63 + .../logicflowruntime_controller_test.go | 84 + .../controller/logicflowservice_controller.go | 63 + .../logicflowservice_controller_test.go | 84 + .../controller/logicplatform_controller.go | 63 + .../logicplatform_controller_test.go | 84 + internal/controller/monitoring/monitoring.go | 53 - internal/controller/openshift/openshift.go | 64 - internal/controller/platform/action.go | 51 - internal/controller/platform/create.go | 53 - .../controller/platform/db_migrator_job.go | 512 - .../platform/db_migrator_job_test.go | 84 - internal/controller/platform/defaults.go | 208 - internal/controller/platform/initialize.go | 177 - internal/controller/platform/k8s.go | 490 - internal/controller/platform/kaniko_cache.go | 143 - internal/controller/platform/monitor.go | 63 - internal/controller/platform/platform.go | 347 - internal/controller/platform/platformutils.go | 98 - .../controller/platform/platformutils_test.go | 108 - .../platform/services/properties.go | 229 - .../services/properties_services_test.go | 277 - .../platform/services/properties_test.go | 146 - .../controller/platform/services/secrets.go | 43 - .../controller/platform/services/services.go | 883 - .../platform/services/services_suite_test.go | 32 - .../platform/services/services_test.go | 57 - .../platform/testdata/platformTest.Dockerfile | 49 - internal/controller/platform/warm.go | 87 - .../profiles/common/constants/objects.go | 27 - .../common/constants/platform_services.go | 95 - .../profiles/common/constants/reconcile.go | 42 - .../profiles/common/constants/workflows.go | 34 - .../common/deployment_status_manager.go | 154 - .../controller/profiles/common/ensurer.go | 251 - .../profiles/common/knative_eventing.go | 83 - .../profiles/common/mutate_visitors.go | 248 - .../profiles/common/object_creators.go | 488 - .../profiles/common/object_creators_test.go | 986 - .../common/persistence/persistence.go | 44 - .../persistence/persistence_suite_test.go | 30 - .../common/persistence/persistence_test.go | 88 - .../profiles/common/persistence/postgresql.go | 237 - .../common/persistence/postgresql_test.go | 150 - .../profiles/common/properties/discovery.go | 139 - .../common/properties/discovery_test.go | 103 - .../profiles/common/properties/knative.go | 54 - .../profiles/common/properties/managed.go | 264 - .../common/properties/managed_test.go | 850 - .../profiles/common/properties/platform.go | 91 - .../common/properties/platform_test.go | 120 - .../properties/properties_suite_test.go | 30 - .../common/properties/properties_test.go | 31 - .../controller/profiles/common/reconciler.go | 137 - .../profiles/common/status_enricher.go | 64 - internal/controller/profiles/common/utils.go | 44 - .../profiles/common/variables/k8s.go | 28 - .../profiles/dev/object_creators_dev.go | 164 - .../profiles/dev/object_creators_dev_test.go | 59 - .../controller/profiles/dev/profile_dev.go | 127 - .../profiles/dev/profile_dev_test.go | 444 - .../controller/profiles/dev/states_dev.go | 284 - .../profiles/dev/status_enricher_dev.go | 128 - .../profiles/dev/status_enricher_dev_test.go | 91 - .../controller/profiles/factory/factory.go | 68 - internal/controller/profiles/gitops/alias.go | 28 - .../profiles/gitops/profile_gitops.go | 60 - .../profiles/gitops/profile_gitops_test.go | 89 - .../profiles/gitops/states_gitops.go | 74 - .../profiles/monitoring/monitoring.go | 67 - .../profiles/preview/deployment_handler.go | 280 - .../preview/deployment_handler_test.go | 231 - .../preview/disruption_budget_handler.go | 105 - .../preview/object_creators_preview.go | 104 - .../profiles/preview/profile_preview.go | 132 - .../profiles/preview/profile_preview_test.go | 233 - .../profiles/preview/states_preview.go | 246 - .../profiles/preview/states_preview_test.go | 55 - internal/controller/profiles/profile.go | 82 - internal/controller/profiles/profile_test.go | 53 - internal/controller/sonataflow_controller.go | 471 - .../controller/sonataflow_controller_test.go | 145 - .../controller/sonataflowbuild_controller.go | 158 - .../sonataflowbuild_controller_test.go | 140 - .../sonataflowclusterplatform_controller.go | 176 - .../sonataflowplatform_controller.go | 430 - .../sonataflowplatform_controller_test.go | 1057 - internal/controller/suite_test.go | 98 +- internal/controller/workflowdef/configmap.go | 99 - internal/controller/workflowdef/events.go | 55 - internal/controller/workflowdef/image.go | 69 - internal/controller/workflowdef/json.go | 47 - internal/controller/workflowdef/json_test.go | 51 - internal/controller/workflowdef/services.go | 33 - internal/controller/workflowdef/utils.go | 141 - .../workflowdef/utils_suite_test.go | 32 - internal/controller/workflowdef/utils_test.go | 286 - internal/controller/workflows/workflows.go | 64 - internal/manager/worker.go | 77 - operator.yaml | 28523 ---------------- test/cfg.go | 34 - test/e2e/clusterplatform_test.go | 315 - test/e2e/e2e_suite_test.go | 259 +- test/e2e/e2e_test.go | 329 + test/e2e/helpers.go | 751 - test/e2e/platform_test.go | 691 - ...low-callbackstatetimeouts-persistence.yaml | 98 - ...ha08_sonataflow-callbackstatetimeouts.yaml | 86 - ...ow.org_v1alpha08_sonataflow-greetings.yaml | 38 - .../01_v1_configmap_subflows.yaml | 85 - .../02_appsv1_deployment_eventlistener.yaml | 60 - .../order-processing/03_discovery_role.yaml | 78 - .../04_v1_configmap_properties.yaml | 25 - ...08_sonataflow_devmode_orderprocessing.yaml | 56 - test/e2e/testdata/order-processing/README.md | 20 - .../hpa/generic-data-index-service-hpa.yaml | 41 - .../gitops/ephemeral/00-broker.yaml | 22 - .../ephemeral/02-sonataflow_platform.yaml | 36 - .../gitops/ephemeral/kustomization.yaml | 27 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../generic_from_platform_cr/01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 63 - .../kustomization.yaml | 34 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 66 - .../kustomization.yaml | 34 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 65 - .../03-data-index-service-hpa.yaml | 41 - .../kustomization.yaml | 35 - .../pg-service/01-postgres.yaml | 89 - .../pg-service/kustomization.yaml | 33 - .../01-sonataflow_platform.yaml | 47 - .../sonataflow-platform/kustomization.yaml | 22 - .../overwritten_by_services/01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 79 - .../kustomization.yaml | 34 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 69 - .../kustomization.yaml | 34 - .../dev/ephemeral/02-sonataflow_platform.yaml | 35 - .../services/dev/ephemeral/kustomization.yaml | 22 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 84 - .../services/dev/postgreSQL/01-postgres.yaml | 89 - .../postgreSQL/02-sonataflow_platform.yaml | 70 - .../dev/postgreSQL/kustomization.yaml | 34 - ...4-sonataflow_callbackstatetimeouts.sw.yaml | 84 - .../01-sonataflow_clusterplatform.yaml | 25 - .../02-sonataflow_platform.yaml | 35 - .../cluster-wide-ephemeral/kustomization.yaml | 20 - .../02-sonataflow_platform.yaml | 33 - .../ephemeral-data-index/kustomization.yaml | 26 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../02-sonataflow_platform.yaml | 33 - .../ephemeral-job-service/kustomization.yaml | 26 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../02-sonataflow_platform.yaml | 31 - .../kustomization.yaml | 26 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../ephemeral-with-workflow/00-broker.yaml | 22 - .../02-sonataflow_platform.yaml | 37 - .../kustomization.yaml | 26 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../services/gitops/ephemeral/00-broker.yaml | 22 - .../ephemeral/02-sonataflow_platform.yaml | 37 - .../gitops/ephemeral/kustomization.yaml | 26 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../platform-level-broker/01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 90 - .../platform-level-broker/broker/broker.yaml | 22 - .../platform-level-broker/kustomization.yaml | 37 - ...4-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../service-level-broker/01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 104 - .../broker/00-broker.yaml | 48 - .../service-level-broker/kustomization.yaml | 37 - .../services/gitops/postgreSQL/00-broker.yaml | 22 - .../gitops/postgreSQL/01-postgres.yaml | 89 - .../postgreSQL/02-sonataflow_platform.yaml | 89 - .../gitops/postgreSQL/kustomization.yaml | 38 - ...4-sonataflow_callbackstatetimeouts.sw.yaml | 95 - ...1-sonataflow.org_v1alpha08_sonataflow.yaml | 47 - ...nataflow.org_v1alpha08_sonataflow_hpa.yaml | 41 - .../persistence/by_service/01-postgres.yaml | 89 - .../by_service/02-sonataflow_platform.yaml | 26 - ...configmap_callbackstatetimeouts-props.yaml | 27 - ...4-sonataflow_callbackstatetimeouts.sw.yaml | 109 - .../persistence/by_service/kustomization.yaml | 36 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 36 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 113 - .../kustomization.yaml | 35 - .../00-broker.yaml | 22 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 73 - ...configmap_callbackstatetimeouts-props.yaml | 27 - ...4-sonataflow_callbackstatetimeouts.sw.yaml | 88 - .../kustomization.yaml | 37 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 36 - ...llbackstatetimeouts-no-persistence.sw.yaml | 91 - .../kustomization.yaml | 35 - .../01-postgres.yaml | 89 - .../02-sonataflow_platform.yaml | 36 - ...3-sonataflow_callbackstatetimeouts.sw.yaml | 92 - .../kustomization.yaml | 35 - .../01-sonataflow_platform.yaml | 24 - .../02-sonataflow_greetings.yaml | 40 - .../k8s_deployment/kustomization.yaml | 23 - test/e2e/workflow_test.go | 720 - test/kubernetes_cli.go | 148 - test/mock_service.go | 141 - .../db_migrator_sonataflow_platform.yaml | 47 - test/testdata/grafana.yaml | 29 - test/testdata/knative_default_broker.yaml | 65 - test/testdata/knative_serving_eventing.yaml | 45 - test/testdata/prometheus.yaml | 72 - ...flow.org_v1alpha08_sonataflow-metainf.yaml | 65 - ...ow.org_v1alpha08_sonataflow-simpleops.yaml | 38 - .../sonataflow.org_v1alpha08_sonataflow.yaml | 61 - ...flow.org_v1alpha08_sonataflow_devmode.yaml | 60 - ...lpha08_sonataflow_devmode_events_http.yaml | 65 - ...lpha08_sonataflow_greetings_datainput.yaml | 66 - ...ow.org_v1alpha08_sonataflow_vet_event.yaml | 85 - ...ataflow.org_v1alpha08_sonataflowbuild.yaml | 50 - ...g_v1alpha08_sonataflowclusterplatform.yaml | 25 - ...flow.org_v1alpha08_sonataflowplatform.yaml | 32 - ...1alpha08_sonataflowplatform_openshift.yaml | 25 - ...alpha08_sonataflowplatform_withBroker.yaml | 49 - .../v1_configmap_greetings_datainput.yaml | 39 - .../v1_configmap_greetings_staticfiles.yaml | 27 - test/utils/utils.go | 262 +- test/yaml.go | 361 - utils/client.go | 4 +- utils/common.go | 32 - utils/crc_test.go | 2 +- utils/kubernetes/autoscaling.go | 22 +- utils/kubernetes/collection.go | 399 - utils/kubernetes/deployment.go | 243 - utils/kubernetes/deployment_failure.go | 4 +- utils/kubernetes/disruption_budget.go | 69 - utils/kubernetes/replace.go | 89 - utils/kubernetes/service.go | 4 +- utils/kubernetes/service_test.go | 14 +- utils/kubernetes/volumes.go | 4 +- utils/openshift/route.go | 49 - utils/openshift/route_test.go | 52 - utils/resources/resources.go | 203 - utils/resources/resources_support.go | 37 - workflowproj/Makefile | 38 - workflowproj/README.md | 105 - workflowproj/camelschema.go | 24 - workflowproj/go.mod | 87 - workflowproj/go.sum | 313 - workflowproj/io.go | 64 - workflowproj/operator.go | 183 - workflowproj/operator_test.go | 394 - workflowproj/resources.go | 73 - workflowproj/resources_test.go | 60 - workflowproj/testdata/mygeneric.wsdl | 138 - workflowproj/testdata/valid-asyncapi.json | 72 - workflowproj/testdata/valid-asyncapi.yaml | 63 - workflowproj/testdata/valid-camelroute.json | 393 - workflowproj/testdata/valid-camelroute.yaml | 275 - workflowproj/testdata/valid-openapi.json | 58 - workflowproj/testdata/valid-openapi.yaml | 53 - .../testdata/workflows/application.properties | 21 - .../testdata/workflows/secret.properties | 25 - .../specs/workflow-service-openapi.json | 59 - .../specs/workflow-service-schema.json | 10 - .../workflow-minimal-invalid.sw.json | 12 - .../workflows/workflow-minimal.sw.json | 16 - .../workflows/workflow-service.sw.json | 30 - workflowproj/workflowproj.go | 463 - workflowproj/workflowproj_test.go | 382 - 553 files changed, 4503 insertions(+), 85748 deletions(-) create mode 100644 .dockerignore create mode 100644 .env create mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/cli-build.yaml delete mode 100644 .github/workflows/cli-e2e.yaml delete mode 100644 .github/workflows/e2e-minimal.yaml delete mode 100644 .github/workflows/e2e.yaml delete mode 100644 .github/workflows/pr-checks.yaml create mode 100644 .golangci.yml create mode 100644 .idea/runConfigurations/Build_Manager.xml create mode 100644 .idea/runConfigurations/Make_Build.xml create mode 100644 .idea/runConfigurations/Make_Test.xml create mode 100644 CLAUDE.md create mode 100644 Dockerfile delete mode 100644 E2E_SETUP.md delete mode 100644 MIGRATION.md delete mode 100644 api/Makefile delete mode 100644 api/go.mod delete mode 100644 api/go.sum delete mode 100644 api/metadata/annotations.go delete mode 100644 api/metadata/annotations_test.go create mode 100644 api/v1/groupversion_info.go create mode 100644 api/v1/logicflowdefinition_types.go create mode 100644 api/v1/logicflowruntime_types.go create mode 100644 api/v1/logicflowservice_types.go create mode 100644 api/v1/logicplatform_types.go create mode 100644 api/v1/zz_generated.deepcopy.go delete mode 100644 api/v1alpha08/conversion.go delete mode 100644 api/v1alpha08/conversion_test.go delete mode 100644 api/v1alpha08/groupversion_info.go delete mode 100644 api/v1alpha08/podtemplate_types.go delete mode 100644 api/v1alpha08/sonataflow_persistence_types.go delete mode 100644 api/v1alpha08/sonataflow_types.go delete mode 100644 api/v1alpha08/sonataflowbuild_types.go delete mode 100644 api/v1alpha08/sonataflowclusterplatform_types.go delete mode 100644 api/v1alpha08/sonataflowclusterplatform_types_support.go delete mode 100644 api/v1alpha08/sonataflowplatform_build_types.go delete mode 100644 api/v1alpha08/sonataflowplatform_devmode_types.go delete mode 100644 api/v1alpha08/sonataflowplatform_property_types.go delete mode 100644 api/v1alpha08/sonataflowplatform_services_types.go delete mode 100644 api/v1alpha08/sonataflowplatform_types.go delete mode 100644 api/v1alpha08/sonataflowplatform_types_support.go delete mode 100644 api/v1alpha08/testdata/camel.sw.json delete mode 100644 api/v1alpha08/testdata/foreach.sw.json delete mode 100644 api/v1alpha08/testdata/invalid.sw.json delete mode 100644 api/v1alpha08/testdata/sonataflow-camel.yaml delete mode 100644 api/v1alpha08/testdata/sonataflow-foreach.yaml delete mode 100644 api/v1alpha08/testdata/sonataflow-invalid.yaml delete mode 100644 api/v1alpha08/zz_generated.deepcopy.go delete mode 100644 bundle/README.md delete mode 100644 bundle/metadata/annotations.yaml delete mode 100644 bundle/tests/scorecard/config.yaml create mode 100644 cli/DEPRECATED.md delete mode 100644 config/crd/bases/.gitkeep create mode 100644 config/crd/bases/logic.kubesmarts.org_logicflowdefinitions.yaml create mode 100644 config/crd/bases/logic.kubesmarts.org_logicflowruntimes.yaml create mode 100644 config/crd/bases/logic.kubesmarts.org_logicflowservices.yaml create mode 100644 config/crd/bases/logic.kubesmarts.org_logicplatforms.yaml delete mode 100644 config/crd/patches/cainjection_in_sonataflowbuilds.yaml delete mode 100644 config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml delete mode 100644 config/crd/patches/cainjection_in_sonataflowplatforms.yaml delete mode 100644 config/crd/patches/cainjection_in_sonataflows.yaml delete mode 100644 config/crd/patches/webhook_in_sonataflowbuilds.yaml delete mode 100644 config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml delete mode 100644 config/crd/patches/webhook_in_sonataflowplatforms.yaml delete mode 100644 config/crd/patches/webhook_in_sonataflows.yaml create mode 100644 config/default/cert_metrics_manager_patch.yaml delete mode 100644 config/default/controllers_config_patch.yaml delete mode 100644 config/default/manager_auth_proxy_patch.yaml delete mode 100644 config/default/manager_config_patch.yaml create mode 100644 config/default/manager_metrics_patch.yaml create mode 100644 config/default/metrics_service.yaml delete mode 100644 config/manager/SonataFlow-Builder.containerfile delete mode 100644 config/manager/controller_manager_config.yaml delete mode 100644 config/manager/controllers_cfg.yaml delete mode 100644 config/manager/manager_env_patch.yaml delete mode 100644 config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml create mode 100644 config/network-policy/allow-metrics-traffic.yaml create mode 100644 config/network-policy/kustomization.yaml create mode 100644 config/prometheus/monitor_tls_patch.yaml delete mode 100644 config/rbac/auth_proxy_client_clusterrole.yaml delete mode 100644 config/rbac/auth_proxy_role.yaml delete mode 100644 config/rbac/auth_proxy_role_binding.yaml delete mode 100644 config/rbac/auth_proxy_service.yaml delete mode 100644 config/rbac/builder_role.yaml delete mode 100644 config/rbac/builder_role_binding.yaml delete mode 100644 config/rbac/knative_role.yaml delete mode 100644 config/rbac/knative_role_binding.yaml create mode 100644 config/rbac/logicflowdefinition_admin_role.yaml create mode 100644 config/rbac/logicflowdefinition_editor_role.yaml create mode 100644 config/rbac/logicflowdefinition_viewer_role.yaml create mode 100644 config/rbac/logicflowruntime_admin_role.yaml create mode 100644 config/rbac/logicflowruntime_editor_role.yaml create mode 100644 config/rbac/logicflowruntime_viewer_role.yaml create mode 100644 config/rbac/logicflowservice_admin_role.yaml create mode 100644 config/rbac/logicflowservice_editor_role.yaml create mode 100644 config/rbac/logicflowservice_viewer_role.yaml create mode 100644 config/rbac/logicplatform_admin_role.yaml create mode 100644 config/rbac/logicplatform_editor_role.yaml create mode 100644 config/rbac/logicplatform_viewer_role.yaml create mode 100644 config/rbac/metrics_auth_role.yaml create mode 100644 config/rbac/metrics_auth_role_binding.yaml create mode 100644 config/rbac/metrics_reader_role.yaml delete mode 100644 config/rbac/openshift_role.yaml delete mode 100644 config/rbac/openshift_role_binding.yaml delete mode 100644 config/rbac/operator_role_binding_leases.yaml delete mode 100644 config/rbac/operator_role_leases.yaml delete mode 100644 config/rbac/service_discovery_role.yaml delete mode 100644 config/rbac/service_discovery_role_binding.yaml delete mode 100644 config/rbac/sonataflow_editor_role.yaml delete mode 100644 config/rbac/sonataflow_viewer_role.yaml delete mode 100644 config/rbac/sonataflowbuild_editor_role.yaml delete mode 100644 config/rbac/sonataflowbuild_viewer_role.yaml delete mode 100644 config/rbac/sonataflowclusterplatform_editor_role.yaml delete mode 100644 config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml delete mode 100644 config/rbac/sonataflowclusterplatform_viewer_role.yaml delete mode 100644 config/rbac/sonataflowplatform_editor_role.yaml delete mode 100644 config/rbac/sonataflowplatform_viewer_role.yaml create mode 100644 config/samples/logic_v1_logicflowdefinition.yaml create mode 100644 config/samples/logic_v1_logicflowruntime.yaml create mode 100644 config/samples/logic_v1_logicflowservice.yaml create mode 100644 config/samples/logic_v1_logicplatform.yaml delete mode 100644 config/samples/sonataflow.org_v1alpha08_sonataflow.yaml delete mode 100644 config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml delete mode 100644 config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml delete mode 100644 config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml delete mode 100644 config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml delete mode 100644 container-builder/Makefile delete mode 100644 container-builder/README.md delete mode 100644 container-builder/api/build_types.go delete mode 100644 container-builder/api/common_type.go delete mode 100644 container-builder/api/doc.go delete mode 100644 container-builder/api/platform_types.go delete mode 100644 container-builder/api/zz_generated.deepcopy.go delete mode 100644 container-builder/builder/kaniko_docker_integration_test.go delete mode 100644 container-builder/builder/kaniko_integration_test_suite.go delete mode 100644 container-builder/builder/kaniko_vanilla.go delete mode 100644 container-builder/builder/kubernetes/action.go delete mode 100644 container-builder/builder/kubernetes/build_pod.go delete mode 100644 container-builder/builder/kubernetes/builder.go delete mode 100644 container-builder/builder/kubernetes/builder_kaniko.go delete mode 100644 container-builder/builder/kubernetes/builder_kaniko_test.go delete mode 100644 container-builder/builder/kubernetes/builder_test.go delete mode 100644 container-builder/builder/kubernetes/env.go delete mode 100644 container-builder/builder/kubernetes/error.go delete mode 100644 container-builder/builder/kubernetes/initialize_pod.go delete mode 100644 container-builder/builder/kubernetes/kaniko.go delete mode 100644 container-builder/builder/kubernetes/kanikoSecurityContext.go delete mode 100644 container-builder/builder/kubernetes/monitor_pod.go delete mode 100644 container-builder/builder/kubernetes/mount.go delete mode 100644 container-builder/builder/kubernetes/mount_test.go delete mode 100644 container-builder/builder/kubernetes/recovery.go delete mode 100644 container-builder/builder/kubernetes/schedule.go delete mode 100644 container-builder/builder/kubernetes/testdata/greetings.sw.json delete mode 100644 container-builder/builder/kubernetes/testdata/sample.Dockerfile delete mode 100644 container-builder/cleaner/cleaner.go delete mode 100644 container-builder/cleaner/docker_integration_test.go delete mode 100644 container-builder/cleaner/docker_integration_test_suite.go delete mode 100644 container-builder/cleaner/registry_docker_integration_test.go delete mode 100644 container-builder/client/client.go delete mode 100644 container-builder/client/fastmapper.go delete mode 100644 container-builder/common/docker.go delete mode 100644 container-builder/common/registry.go delete mode 100644 container-builder/common/registry_docker.go delete mode 100644 container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml delete mode 100644 container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml delete mode 100644 container-builder/examples/app.yaml delete mode 100644 container-builder/examples/dockerfiles/SonataFlow.dockerfile delete mode 100644 container-builder/examples/service.yaml delete mode 100644 container-builder/examples/sources/sonataflowgreetings.sw.json delete mode 100644 container-builder/go.mod delete mode 100644 container-builder/go.sum delete mode 100644 container-builder/hack/boilerplate.go.txt delete mode 100755 container-builder/hack/btrfs_installed_tag.sh delete mode 100755 container-builder/hack/btrfs_tag.sh delete mode 100644 container-builder/main.go delete mode 100644 container-builder/util/log/log.go delete mode 100644 container-builder/util/minikube/registry.go delete mode 100644 container-builder/util/registry/kep_1755.go delete mode 100644 container-builder/util/test/client.go delete mode 100644 container-builder/util/util.go delete mode 100644 docs/CLI_E2E_TODO.md delete mode 100644 docs/CLI_MIGRATION_METADATA.md delete mode 100644 docs/CLI_MIGRATION_PLAN.md create mode 100644 docs/migration/operator-sdk-migration-analysis.md delete mode 100644 env/index.js delete mode 100644 go.work delete mode 100644 go.work.sum delete mode 100755 hack/addheaders.sh delete mode 100755 hack/bump-version.sh delete mode 100755 hack/create-kind-cluster-with-registry.sh delete mode 100755 hack/env.sh delete mode 100755 hack/go-path.sh delete mode 100755 hack/goimports.sh delete mode 100755 hack/install-operator-sdk.sh delete mode 100644 hack/license-header.txt delete mode 100755 hack/local/run-e2e-crc.sh delete mode 100755 hack/local/run-e2e.sh delete mode 100755 hack/local/run-operator.sh delete mode 100755 hack/pull-test-images.sh delete mode 100755 hack/setup-cekit.sh delete mode 100644 hack/update_patch_env.py delete mode 100644 images/bundle.yaml delete mode 100644 images/manager.yaml delete mode 100644 images/modules/org.apache.kie.sonataflow.bundle/module.yaml delete mode 100755 images/modules/org.apache.kie.sonataflow.goModDownload/install.sh delete mode 100644 images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml delete mode 100644 images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh delete mode 100644 images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml delete mode 100644 images/requirements.txt delete mode 100644 internal/controller/builder/builder.go delete mode 100644 internal/controller/builder/config.go delete mode 100644 internal/controller/builder/containerbuilder.go delete mode 100644 internal/controller/builder/kogitoserverlessbuild_manager.go delete mode 100644 internal/controller/builder/kogitoserverlessbuild_manager_test.go delete mode 100644 internal/controller/builder/openshiftbuilder.go delete mode 100644 internal/controller/builder/openshiftbuilder_test.go delete mode 100644 internal/controller/cfg/controllers_cfg.go delete mode 100644 internal/controller/cfg/controllers_cfg_test.go delete mode 100644 internal/controller/cfg/testdata/controllers-cfg-invalid.yaml delete mode 100644 internal/controller/cfg/testdata/controllers-cfg-test.yaml delete mode 100644 internal/controller/clusterplatform/action.go delete mode 100644 internal/controller/clusterplatform/clusterplatform.go delete mode 100644 internal/controller/clusterplatform/defaults.go delete mode 100644 internal/controller/clusterplatform/initialize.go delete mode 100644 internal/controller/const.go delete mode 100644 internal/controller/discovery/discovery.go delete mode 100644 internal/controller/discovery/discovery_knative_test.go delete mode 100644 internal/controller/discovery/discovery_openshift_test.go delete mode 100644 internal/controller/discovery/discovery_test.go delete mode 100644 internal/controller/discovery/knative_catalog.go delete mode 100644 internal/controller/discovery/kubernetes_catalog.go delete mode 100644 internal/controller/discovery/kubernetes_constants.go delete mode 100644 internal/controller/discovery/openshift_catalog.go delete mode 100644 internal/controller/discovery/port_utils.go delete mode 100644 internal/controller/discovery/port_utils_test.go delete mode 100644 internal/controller/discovery/queries.go delete mode 100644 internal/controller/discovery/queries_test.go delete mode 100644 internal/controller/discovery/test_utils.go delete mode 100644 internal/controller/discovery/uri_parser.go delete mode 100644 internal/controller/discovery/uri_parser_test.go delete mode 100644 internal/controller/discovery/uri_utils.go delete mode 100644 internal/controller/discovery/uri_utils_test.go delete mode 100644 internal/controller/eventing/workflowdef_events.go delete mode 100644 internal/controller/knative/knative.go create mode 100644 internal/controller/logicflowdefinition_controller.go create mode 100644 internal/controller/logicflowdefinition_controller_test.go create mode 100644 internal/controller/logicflowruntime_controller.go create mode 100644 internal/controller/logicflowruntime_controller_test.go create mode 100644 internal/controller/logicflowservice_controller.go create mode 100644 internal/controller/logicflowservice_controller_test.go create mode 100644 internal/controller/logicplatform_controller.go create mode 100644 internal/controller/logicplatform_controller_test.go delete mode 100644 internal/controller/monitoring/monitoring.go delete mode 100644 internal/controller/openshift/openshift.go delete mode 100644 internal/controller/platform/action.go delete mode 100644 internal/controller/platform/create.go delete mode 100644 internal/controller/platform/db_migrator_job.go delete mode 100644 internal/controller/platform/db_migrator_job_test.go delete mode 100644 internal/controller/platform/defaults.go delete mode 100644 internal/controller/platform/initialize.go delete mode 100644 internal/controller/platform/k8s.go delete mode 100644 internal/controller/platform/kaniko_cache.go delete mode 100644 internal/controller/platform/monitor.go delete mode 100644 internal/controller/platform/platform.go delete mode 100644 internal/controller/platform/platformutils.go delete mode 100644 internal/controller/platform/platformutils_test.go delete mode 100644 internal/controller/platform/services/properties.go delete mode 100644 internal/controller/platform/services/properties_services_test.go delete mode 100644 internal/controller/platform/services/properties_test.go delete mode 100644 internal/controller/platform/services/secrets.go delete mode 100644 internal/controller/platform/services/services.go delete mode 100644 internal/controller/platform/services/services_suite_test.go delete mode 100644 internal/controller/platform/services/services_test.go delete mode 100644 internal/controller/platform/testdata/platformTest.Dockerfile delete mode 100644 internal/controller/platform/warm.go delete mode 100644 internal/controller/profiles/common/constants/objects.go delete mode 100644 internal/controller/profiles/common/constants/platform_services.go delete mode 100644 internal/controller/profiles/common/constants/reconcile.go delete mode 100644 internal/controller/profiles/common/constants/workflows.go delete mode 100644 internal/controller/profiles/common/deployment_status_manager.go delete mode 100644 internal/controller/profiles/common/ensurer.go delete mode 100644 internal/controller/profiles/common/knative_eventing.go delete mode 100644 internal/controller/profiles/common/mutate_visitors.go delete mode 100644 internal/controller/profiles/common/object_creators.go delete mode 100644 internal/controller/profiles/common/object_creators_test.go delete mode 100644 internal/controller/profiles/common/persistence/persistence.go delete mode 100644 internal/controller/profiles/common/persistence/persistence_suite_test.go delete mode 100644 internal/controller/profiles/common/persistence/persistence_test.go delete mode 100644 internal/controller/profiles/common/persistence/postgresql.go delete mode 100644 internal/controller/profiles/common/persistence/postgresql_test.go delete mode 100644 internal/controller/profiles/common/properties/discovery.go delete mode 100644 internal/controller/profiles/common/properties/discovery_test.go delete mode 100644 internal/controller/profiles/common/properties/knative.go delete mode 100644 internal/controller/profiles/common/properties/managed.go delete mode 100644 internal/controller/profiles/common/properties/managed_test.go delete mode 100644 internal/controller/profiles/common/properties/platform.go delete mode 100644 internal/controller/profiles/common/properties/platform_test.go delete mode 100644 internal/controller/profiles/common/properties/properties_suite_test.go delete mode 100644 internal/controller/profiles/common/properties/properties_test.go delete mode 100644 internal/controller/profiles/common/reconciler.go delete mode 100644 internal/controller/profiles/common/status_enricher.go delete mode 100644 internal/controller/profiles/common/utils.go delete mode 100644 internal/controller/profiles/common/variables/k8s.go delete mode 100644 internal/controller/profiles/dev/object_creators_dev.go delete mode 100644 internal/controller/profiles/dev/object_creators_dev_test.go delete mode 100644 internal/controller/profiles/dev/profile_dev.go delete mode 100644 internal/controller/profiles/dev/profile_dev_test.go delete mode 100644 internal/controller/profiles/dev/states_dev.go delete mode 100644 internal/controller/profiles/dev/status_enricher_dev.go delete mode 100644 internal/controller/profiles/dev/status_enricher_dev_test.go delete mode 100644 internal/controller/profiles/factory/factory.go delete mode 100644 internal/controller/profiles/gitops/alias.go delete mode 100644 internal/controller/profiles/gitops/profile_gitops.go delete mode 100644 internal/controller/profiles/gitops/profile_gitops_test.go delete mode 100644 internal/controller/profiles/gitops/states_gitops.go delete mode 100644 internal/controller/profiles/monitoring/monitoring.go delete mode 100644 internal/controller/profiles/preview/deployment_handler.go delete mode 100644 internal/controller/profiles/preview/deployment_handler_test.go delete mode 100644 internal/controller/profiles/preview/disruption_budget_handler.go delete mode 100644 internal/controller/profiles/preview/object_creators_preview.go delete mode 100644 internal/controller/profiles/preview/profile_preview.go delete mode 100644 internal/controller/profiles/preview/profile_preview_test.go delete mode 100644 internal/controller/profiles/preview/states_preview.go delete mode 100644 internal/controller/profiles/preview/states_preview_test.go delete mode 100644 internal/controller/profiles/profile.go delete mode 100644 internal/controller/profiles/profile_test.go delete mode 100644 internal/controller/sonataflow_controller.go delete mode 100644 internal/controller/sonataflow_controller_test.go delete mode 100644 internal/controller/sonataflowbuild_controller.go delete mode 100644 internal/controller/sonataflowbuild_controller_test.go delete mode 100644 internal/controller/sonataflowclusterplatform_controller.go delete mode 100644 internal/controller/sonataflowplatform_controller.go delete mode 100644 internal/controller/sonataflowplatform_controller_test.go delete mode 100644 internal/controller/workflowdef/configmap.go delete mode 100644 internal/controller/workflowdef/events.go delete mode 100644 internal/controller/workflowdef/image.go delete mode 100644 internal/controller/workflowdef/json.go delete mode 100644 internal/controller/workflowdef/json_test.go delete mode 100644 internal/controller/workflowdef/services.go delete mode 100644 internal/controller/workflowdef/utils.go delete mode 100644 internal/controller/workflowdef/utils_suite_test.go delete mode 100644 internal/controller/workflowdef/utils_test.go delete mode 100644 internal/controller/workflows/workflows.go delete mode 100644 internal/manager/worker.go delete mode 100644 operator.yaml delete mode 100644 test/cfg.go delete mode 100644 test/e2e/clusterplatform_test.go create mode 100644 test/e2e/e2e_test.go delete mode 100644 test/e2e/helpers.go delete mode 100644 test/e2e/platform_test.go delete mode 100644 test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts-persistence.yaml delete mode 100644 test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts.yaml delete mode 100644 test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-greetings.yaml delete mode 100644 test/e2e/testdata/order-processing/01_v1_configmap_subflows.yaml delete mode 100644 test/e2e/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml delete mode 100644 test/e2e/testdata/order-processing/03_discovery_role.yaml delete mode 100644 test/e2e/testdata/order-processing/04_v1_configmap_properties.yaml delete mode 100644 test/e2e/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml delete mode 100644 test/e2e/testdata/order-processing/README.md delete mode 100644 test/e2e/testdata/platform/hpa/generic-data-index-service-hpa.yaml delete mode 100644 test/e2e/testdata/platform/noservices/gitops/ephemeral/00-broker.yaml delete mode 100644 test/e2e/testdata/platform/noservices/gitops/ephemeral/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/noservices/gitops/ephemeral/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/noservices/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/03-data-index-service-hpa.yaml delete mode 100644 test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/01-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/overwritten_by_services/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/persistence/service_based_db_migration/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/persistence/service_based_db_migration/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/persistence/service_based_db_migration/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/ephemeral/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/postgreSQL/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/postgreSQL/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-data-index/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-data-index/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-job-service/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-job-service/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/00-broker.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral/00-broker.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/broker/broker.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/service-level-broker/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/service-level-broker/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/service-level-broker/broker/00-broker.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/knative/service-level-broker/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/postgreSQL/00-broker.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/postgreSQL/01-postgres.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/postgreSQL/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/postgreSQL/kustomization.yaml delete mode 100644 test/e2e/testdata/platform/services/gitops/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow.yaml delete mode 100644 test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/by_service/01-postgres.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/by_service/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/by_service/03-configmap_callbackstatetimeouts-props.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/by_service/04-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/by_service/kustomization.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/01-postgres.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/kustomization.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/00-broker.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/01-postgres.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/03-configmap_callbackstatetimeouts-props.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/04-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/kustomization.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/01-postgres.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/kustomization.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/01-postgres.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml delete mode 100644 test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/kustomization.yaml delete mode 100644 test/e2e/testdata/workflows/prometheus/k8s_deployment/01-sonataflow_platform.yaml delete mode 100644 test/e2e/testdata/workflows/prometheus/k8s_deployment/02-sonataflow_greetings.yaml delete mode 100644 test/e2e/testdata/workflows/prometheus/k8s_deployment/kustomization.yaml delete mode 100644 test/e2e/workflow_test.go delete mode 100644 test/kubernetes_cli.go delete mode 100644 test/mock_service.go delete mode 100644 test/testdata/db_migrator_sonataflow_platform.yaml delete mode 100644 test/testdata/grafana.yaml delete mode 100644 test/testdata/knative_default_broker.yaml delete mode 100644 test/testdata/knative_serving_eventing.yaml delete mode 100644 test/testdata/prometheus.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml delete mode 100644 test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withBroker.yaml delete mode 100644 test/testdata/v1_configmap_greetings_datainput.yaml delete mode 100644 test/testdata/v1_configmap_greetings_staticfiles.yaml delete mode 100644 test/yaml.go delete mode 100644 utils/kubernetes/collection.go delete mode 100644 utils/kubernetes/deployment.go delete mode 100644 utils/kubernetes/disruption_budget.go delete mode 100644 utils/kubernetes/replace.go delete mode 100644 utils/openshift/route.go delete mode 100644 utils/openshift/route_test.go delete mode 100644 utils/resources/resources.go delete mode 100644 utils/resources/resources_support.go delete mode 100644 workflowproj/Makefile delete mode 100644 workflowproj/README.md delete mode 100644 workflowproj/camelschema.go delete mode 100644 workflowproj/go.mod delete mode 100644 workflowproj/go.sum delete mode 100644 workflowproj/io.go delete mode 100644 workflowproj/operator.go delete mode 100644 workflowproj/operator_test.go delete mode 100644 workflowproj/resources.go delete mode 100644 workflowproj/resources_test.go delete mode 100644 workflowproj/testdata/mygeneric.wsdl delete mode 100644 workflowproj/testdata/valid-asyncapi.json delete mode 100644 workflowproj/testdata/valid-asyncapi.yaml delete mode 100644 workflowproj/testdata/valid-camelroute.json delete mode 100644 workflowproj/testdata/valid-camelroute.yaml delete mode 100644 workflowproj/testdata/valid-openapi.json delete mode 100644 workflowproj/testdata/valid-openapi.yaml delete mode 100644 workflowproj/testdata/workflows/application.properties delete mode 100644 workflowproj/testdata/workflows/secret.properties delete mode 100644 workflowproj/testdata/workflows/specs/workflow-service-openapi.json delete mode 100644 workflowproj/testdata/workflows/specs/workflow-service-schema.json delete mode 100644 workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json delete mode 100644 workflowproj/testdata/workflows/workflow-minimal.sw.json delete mode 100644 workflowproj/testdata/workflows/workflow-service.sw.json delete mode 100644 workflowproj/workflowproj.go delete mode 100644 workflowproj/workflowproj_test.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..a3aab7af --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Ignore build and test binaries. +bin/ diff --git a/.env b/.env new file mode 100644 index 00000000..abccecca --- /dev/null +++ b/.env @@ -0,0 +1,26 @@ +# Operator version and build configuration +VERSION=2.0.0-snapshot +IMAGE_TAG=2.0.0 +PLATFORM_TAG=2.0.0 + +# Registry and image naming +REGISTRY=quay.io +ACCOUNT=kubesmarts +OPERATOR_NAME=logic-operator + +# Related images (pointing to Kubesmarts Quay.io registry) +# Using main tag for latest development images +RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL=quay.io/kubesmarts/incubator-kie-kogito-jobs-service-postgresql:main +RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL=quay.io/kubesmarts/incubator-kie-kogito-jobs-service-ephemeral:main +RELATED_IMAGE_DATA_INDEX_POSTGRESQL=quay.io/kubesmarts/incubator-kie-kogito-data-index-postgresql:main +RELATED_IMAGE_DATA_INDEX_EPHEMERAL=quay.io/kubesmarts/incubator-kie-kogito-data-index-ephemeral:main +RELATED_IMAGE_BASE_BUILDER=quay.io/kubesmarts/incubator-kie-sonataflow-builder:main +RELATED_IMAGE_DEVMODE=quay.io/kubesmarts/incubator-kie-sonataflow-devmode:main +RELATED_IMAGE_DB_MIGRATOR_TOOL=quay.io/kubesmarts/incubator-kie-kogito-db-migrator:main + +# Image digest pinning tool (docker, podman, or skopeo) +PIN_IMAGE_SHA_BUNDLE_TOOL=docker + +# CLI build metadata +QUARKUS_VERSION=3.8.1 +QUARKUS_PLATFORM_GROUP_ID=io.quarkus.platform diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..20749f36 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,44 @@ +name: CI + +on: + push: + branches: + - main + - feat/** + pull_request: + branches: + - main + +jobs: + validate: + name: Validate Code + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.26' + + - name: Check go fmt + run: | + OUTPUT=$(go fmt ./...) + if [ -n "$OUTPUT" ]; then + echo "The following files are not formatted:" + echo "$OUTPUT" + echo "Please run 'go fmt ./...' locally and commit the changes" + exit 1 + fi + + - name: Run linter + run: make lint + + - name: Run build + run: make build + + - name: Run unit tests + run: | + make manifests generate fmt vet setup-envtest + KUBEBUILDER_ASSETS="$(bin/setup-envtest use 1.35.0 --bin-dir $(pwd)/bin -p path)" go test $(go list ./... | grep -v /e2e) diff --git a/.github/workflows/cli-build.yaml b/.github/workflows/cli-build.yaml deleted file mode 100644 index 1d99b14b..00000000 --- a/.github/workflows/cli-build.yaml +++ /dev/null @@ -1,112 +0,0 @@ -name: CLI Build and Test - -on: - push: - branches: [main, master] - paths: - - 'cli/**' - - '.github/workflows/cli-build.yaml' - pull_request: - branches: [main, master] - paths: - - 'cli/**' - - '.github/workflows/cli-build.yaml' - -jobs: - build-and-test: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - include: - - os: ubuntu-latest - binary: kn-workflow-linux-amd64 - - os: macos-latest - binary: kn-workflow-darwin-arm64 - - os: windows-latest - binary: kn-workflow-windows-amd64.exe - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Copy .env configuration - shell: bash - run: cp .env.example .env - - - name: Run unit tests - working-directory: cli - run: go test -v ./... - - - name: Build CLI - working-directory: cli - shell: bash - run: | - if [ "$RUNNER_OS" == "Linux" ]; then - make build-linux-amd64 - elif [ "$RUNNER_OS" == "macOS" ]; then - make build-darwin-arm64 - elif [ "$RUNNER_OS" == "Windows" ]; then - make build-win32-amd64 - fi - - - name: Test CLI version command - working-directory: cli - shell: bash - run: | - if [ "$RUNNER_OS" == "Windows" ]; then - ./dist/kn-workflow-windows-amd64.exe version - elif [ "$RUNNER_OS" == "macOS" ]; then - ./dist/kn-workflow-darwin-arm64 version - else - ./dist/kn-workflow-linux-amd64 version - fi - - - name: Upload binary - uses: actions/upload-artifact@v4 - with: - name: cli-${{ matrix.os }} - path: cli/dist/${{ matrix.binary }} - retention-days: 7 - - build-all-platforms: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Build all platforms - working-directory: cli - run: make build-all - - - name: Verify all binaries - working-directory: cli - run: | - ls -lh dist/ - [ -f dist/kn-workflow-linux-amd64 ] - [ -f dist/kn-workflow-darwin-amd64 ] - [ -f dist/kn-workflow-darwin-arm64 ] - [ -f dist/kn-workflow-windows-amd64.exe ] - - - name: Upload all binaries - uses: actions/upload-artifact@v4 - with: - name: cli-all-platforms - path: cli/dist/* - retention-days: 30 diff --git a/.github/workflows/cli-e2e.yaml b/.github/workflows/cli-e2e.yaml deleted file mode 100644 index ad46c08c..00000000 --- a/.github/workflows/cli-e2e.yaml +++ /dev/null @@ -1,88 +0,0 @@ -name: CLI E2E Tests - -on: - push: - branches: [main, master] - paths: - - 'cli/**' - - '.github/workflows/cli-e2e.yaml' - pull_request: - branches: [main, master] - paths: - - 'cli/**' - - '.github/workflows/cli-e2e.yaml' - workflow_dispatch: - -jobs: - e2e-tests: - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Build CLI - working-directory: cli - run: make build - - - name: Run non-operator e2e tests - working-directory: cli - env: - SKIP_OPERATOR_INSTALL: "true" - run: | - mkdir -p dist-tests-e2e - # Run CLI e2e tests that don't require Kubernetes/operator - # These tests verify local CLI functionality: create, convert, gen-manifest - # - # Tests running (8 total): - # - TestCreateProjectSuccess (create workflow project) - # - TestCreateProjectFail (validate errors) - # - TestGenManifestProjectSuccess (generate K8s manifests) - # - TestQuarkusCreateProjectSuccess (create Quarkus project) - # - TestQuarkusCreateProjectFail (validate errors) - # - TestQuarkusConvertProjectSuccess (convert to Quarkus) - # - TestQuarkusConvertProjectFailed (validate errors) - # - TestQuarkusConvertProjectFailedAlreadyQuarkus (validate already converted) - # - # Tests skipped: - # - Deploy tests (require OLM-based operator installation) - # - Build/run tests (require Docker) - go test -v ./e2e-tests/... -tags e2e_tests \ - -run "TestCreateProject|TestQuarkusCreateProject|TestQuarkusConvertProject|TestGenManifestProject" \ - -timeout 10m 2>&1 | tee ./dist-tests-e2e/go-test-output-e2e.txt - - - name: Generate JUnit report - if: always() - working-directory: cli - run: | - if [ -f ./dist-tests-e2e/go-test-output-e2e.txt ]; then - go run github.com/jstemmer/go-junit-report/v2 \ - -in ./dist-tests-e2e/go-test-output-e2e.txt \ - -out ./dist-tests-e2e/junit-report.xml || true - fi - - - name: Upload test results - if: always() - uses: actions/upload-artifact@v4 - with: - name: cli-e2e-test-results - path: cli/dist-tests-e2e/ - retention-days: 7 - - - name: Display test summary - if: always() - working-directory: cli - run: | - if [ -f ./dist-tests-e2e/go-test-output-e2e.txt ]; then - echo "=== Test Output Summary ===" - grep -E "PASS|FAIL|RUN" ./dist-tests-e2e/go-test-output-e2e.txt | tail -20 - fi diff --git a/.github/workflows/e2e-minimal.yaml b/.github/workflows/e2e-minimal.yaml deleted file mode 100644 index 45b7aeb7..00000000 --- a/.github/workflows/e2e-minimal.yaml +++ /dev/null @@ -1,158 +0,0 @@ -name: E2E Tests (Quick - PR Only) - -on: - pull_request: - branches: [main, master] - workflow_dispatch: - -jobs: - e2e-minimal: - runs-on: ubuntu-latest - timeout-minutes: 30 - defaults: - run: - shell: bash - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Install CEKit - uses: cekit/actions-setup-cekit@v1.1.7 - - - name: Verify CEKit installation - run: cekit --version - - - name: Install operator-sdk - run: | - export OPERATOR_SDK_VERSION=v1.35.0 - curl -sSLo /tmp/operator-sdk "https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk_linux_amd64" - chmod +x /tmp/operator-sdk - sudo mv /tmp/operator-sdk /usr/local/bin/operator-sdk - operator-sdk version - - - name: Save Go bin directory to environment - run: | - GO_BIN_DIR=$(dirname $(which go)) - echo "GO_BIN_DIR=$GO_BIN_DIR" >> $GITHUB_ENV - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Build operator - env: - GO_BIN_PATH: ${{ env.GO_BIN_DIR }} - run: | - export PATH="$GO_BIN_PATH:$PATH" - make container-build IMG=quay.io/kubesmarts/logic-operator:2.0.0 - - - name: Create KinD cluster - run: make create-cluster - - - name: Load operator image to KinD - run: make load-docker-image IMG=quay.io/kubesmarts/logic-operator:2.0.0 - - - name: Install operator - run: make deploy IMG=quay.io/kubesmarts/logic-operator:2.0.0 - - - name: Deploy Knative - run: make deploy-knative - - - name: Wait for operator to be ready - run: kubectl wait pod -A -l app.kubernetes.io/name=sonataflow-operator --for condition=Ready --timeout 120s - - - name: Verify operator health - run: | - echo "=== Operator deployment ===" - kubectl get deployment -n sonataflow-operator-system - echo "" - echo "=== Operator pods ===" - kubectl get pods -n sonataflow-operator-system -o wide - echo "" - echo "=== Operator logs (startup) ===" - kubectl logs -n sonataflow-operator-system deployment/sonataflow-operator-controller-manager -c manager --tail=50 - - - name: Run critical platform tests only - env: - PREBUILT_WORKFLOWS: "callbackstatetimeouts,callbackstatetimeouts-persistence" - run: | - # Run only gitops with postgresql (the test we just fixed) and one basic platform test - # PREBUILT_WORKFLOWS env var limits to only the 2 workflows we actually use - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/platform_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output \ - -ginkgo.focus="postgreSQL.*gitops|ephemeral.*gitops" \ - -ginkgo.junit-report=./e2e-test-report-platform-minimal.xml -timeout 20m - - - name: Run basic workflow tests (one ephemeral test only) - env: - PREBUILT_WORKFLOWS: "callbackstatetimeouts,callbackstatetimeouts-persistence" - run: | - # Run only one basic ephemeral workflow test - # PREBUILT_WORKFLOWS must match the platform test step to avoid rebuilding - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output \ - -ginkgo.label-filter=flows-ephemeral \ - -ginkgo.focus="preview profile" \ - -ginkgo.junit-report=./e2e-test-report-workflow-minimal.xml -timeout 10m - - - name: Collect cluster logs on failure - if: failure() - run: | - echo "=== Operator deployment status ===" - kubectl get deployment -n sonataflow-operator-system -o wide || true - echo "" - echo "=== Operator pods ===" - kubectl get pods -n sonataflow-operator-system -o wide || true - echo "" - echo "=== Operator logs (last 200 lines) ===" - kubectl logs -n sonataflow-operator-system deployment/sonataflow-operator-controller-manager -c manager --tail=200 || true - echo "" - echo "=== SonataFlow CRs ===" - kubectl get sonataflow -A -o wide || true - echo "" - echo "=== SonataFlow CR details (YAML) ===" - kubectl get sonataflow -A -o yaml || true - echo "" - echo "=== SonataFlowPlatform CRs ===" - kubectl get sonataflowplatform -A -o wide || true - echo "" - echo "=== SonataFlowPlatform details (YAML) ===" - kubectl get sonataflowplatform -A -o yaml || true - echo "" - echo "=== Workflow application pods ===" - kubectl get pods -A -l sonataflow.org/workflow-app --show-labels || true - echo "" - echo "=== Platform service pods ===" - kubectl get pods -A -l app.kubernetes.io/name -o wide || true - echo "" - echo "=== Workflow pod logs (current) ===" - for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do - for pod in $(kubectl get pods -n $ns -l sonataflow.org/workflow-app --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true); do - echo "--- Logs for $ns/$pod (current) ---" - kubectl logs -n $ns $pod --tail=100 || true - echo "" - done - done - echo "" - echo "=== Workflow pod logs (previous) ===" - for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do - for pod in $(kubectl get pods -n $ns -l sonataflow.org/workflow-app --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true); do - echo "--- Logs for $ns/$pod (previous container) ---" - kubectl logs -n $ns $pod --previous --tail=100 2>/dev/null || echo "No previous container logs" - echo "" - done - done - echo "" - echo "=== All pods ===" - kubectl get pods -A -o wide || true - echo "" - echo "=== Recent events (last 100) ===" - kubectl get events -A --sort-by='.metadata.creationTimestamp' | tail -100 || true diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml deleted file mode 100644 index a77d171b..00000000 --- a/.github/workflows/e2e.yaml +++ /dev/null @@ -1,186 +0,0 @@ -name: E2E Tests (Full Suite - Manual) - -on: - workflow_dispatch: - -jobs: - e2e: - runs-on: ubuntu-latest - timeout-minutes: 30 - strategy: - fail-fast: false - matrix: - test-suite: - - name: platform - label: platform - focus: "" - - name: cluster - label: cluster - focus: "" - - name: flows-monitoring - label: flows-monitoring - focus: "" - - name: flows-persistence - label: flows-persistence - focus: "" - - name: flows-ephemeral - label: flows-ephemeral - focus: "" - - name: E2E (${{ matrix.test-suite.name }}) - - defaults: - run: - shell: bash - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Install CEKit - uses: cekit/actions-setup-cekit@v1.1.7 - - - name: Verify CEKit installation - run: cekit --version - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Install build tools - run: | - # Install to local bin directory (matching Makefile's LOCALBIN) - LOCALBIN=$(pwd)/bin - mkdir -p $LOCALBIN - GOBIN=$LOCALBIN go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.4 - # Install kustomize with version suffix to match Makefile expectations - GOBIN=$LOCALBIN go install sigs.k8s.io/kustomize/kustomize/v5@v5.4.1 - mv $LOCALBIN/kustomize $LOCALBIN/kustomize-v5.4.1 - - - name: Generate manifests (early to catch errors before long build) - run: make manifests - - - name: Free up disk space - run: | - # Remove unnecessary files to free up ~10GB before pulling/building images - # NOTE: DO NOT remove $AGENT_TOOLSDIRECTORY - it contains our Go installation! - sudo rm -rf /usr/share/dotnet - sudo rm -rf /opt/ghc - sudo rm -rf /usr/local/share/boost - df -h - - - name: Build operator image - run: make container-build - - - name: Clean up build layers - run: | - # Remove dangling images and build cache from CEKit (keeps our tagged images) - docker image prune -f - docker builder prune -f - df -h - - - name: Create KIND cluster with registry - run: make create-cluster - - - name: Load operator image into KIND - run: make load-docker-image - - - name: Deploy operator - run: make deploy-only - - - name: Deploy Knative - run: make deploy-knative - - - name: Deploy Prometheus - run: make deploy-prometheus - - - name: Wait for operator to be ready - run: kubectl wait pod -A -l app.kubernetes.io/name=sonataflow-operator --for condition=Ready --timeout 120s - - - name: Verify operator health - run: | - echo "=== Operator deployment ===" - kubectl get deployment -n sonataflow-operator-system - echo "" - echo "=== Operator pods ===" - kubectl get pods -n sonataflow-operator-system -o wide - echo "" - echo "=== Operator logs (startup) ===" - kubectl logs -n sonataflow-operator-system deployment/sonataflow-operator-controller-manager -c manager --tail=50 - - - name: Run E2E tests (${{ matrix.test-suite.name }}) - run: make test-e2e label=${{ matrix.test-suite.label }} - - - name: Collect cluster logs on failure - if: failure() - run: | - echo "=== Operator deployment status ===" - kubectl get deployment -n sonataflow-operator-system -o wide || true - echo "" - echo "=== Operator pods ===" - kubectl get pods -n sonataflow-operator-system -o wide || true - echo "" - echo "=== Operator logs (last 200 lines) ===" - kubectl logs -n sonataflow-operator-system deployment/sonataflow-operator-controller-manager -c manager --tail=200 || true - echo "" - echo "=== SonataFlow CRs ===" - kubectl get sonataflow -A -o wide || true - echo "" - echo "=== SonataFlow CR details (YAML) ===" - kubectl get sonataflow -A -o yaml || true - echo "" - echo "=== SonataFlowPlatform CRs ===" - kubectl get sonataflowplatform -A -o wide || true - echo "" - echo "=== SonataFlowPlatform details (YAML) ===" - kubectl get sonataflowplatform -A -o yaml || true - echo "" - echo "=== Workflow application pods ===" - kubectl get pods -A -l app.kubernetes.io/part-of=sonataflow -o wide || true - echo "" - echo "=== Platform service pods ===" - kubectl get pods -A -l 'app.kubernetes.io/name in (jobs-service,data-index-service)' -o wide || true - echo "" - echo "=== Workflow pod logs (current) ===" - for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do - for pod in $(kubectl get pods -n $ns -l sonataflow.org/workflow-app --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true); do - echo "--- Logs for $ns/$pod (current) ---" - kubectl logs -n $ns $pod --tail=100 || true - echo "" - done - done - echo "=== Workflow pod logs (previous) ===" - for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do - for pod in $(kubectl get pods -n $ns -l sonataflow.org/workflow-app --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true); do - echo "--- Logs for $ns/$pod (previous container) ---" - kubectl logs -n $ns $pod --previous --tail=100 2>/dev/null || echo "No previous container logs" - echo "" - done - done - echo "" - echo "=== All pods ===" - kubectl get pods -A -o wide - echo "" - echo "=== Recent events (last 100) ===" - kubectl get events -A --sort-by='.lastTimestamp' | tail -100 - - - name: Upload test results - if: always() - uses: actions/upload-artifact@v4 - with: - name: e2e-test-results-${{ matrix.test-suite.name }} - path: | - e2e-test-report-*.xml - test/logs/ - retention-days: 7 - - - name: Cleanup - if: always() - run: make delete-cluster || true diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml deleted file mode 100644 index e241220d..00000000 --- a/.github/workflows/pr-checks.yaml +++ /dev/null @@ -1,130 +0,0 @@ -name: PR Checks - -on: - pull_request: - branches: [main, master] - -jobs: - lint-and-test: - runs-on: ubuntu-latest - timeout-minutes: 20 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Save Go bin directory to environment - run: | - GO_BIN_DIR=$(dirname $(which go)) - echo "GO_BIN_DIR=$GO_BIN_DIR" >> $GITHUB_ENV - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Install operator-sdk - run: | - export OPERATOR_SDK_VERSION=v1.35.0 - curl -sSLo /tmp/operator-sdk "https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk_linux_amd64" - chmod +x /tmp/operator-sdk - sudo mv /tmp/operator-sdk /usr/local/bin/operator-sdk - operator-sdk version - - - name: Generate bundle (required for unit tests) - run: make bundle - - - name: Format generated code - run: gofmt -s -w . - - - name: Run go fmt check - run: | - # Exclude target/ directory (build artifacts) - UNFORMATTED=$(gofmt -s -l . | grep -v '^target/' || true) - if [ -n "$UNFORMATTED" ]; then - echo "The following files need formatting:" - echo "$UNFORMATTED" - exit 1 - fi - - - name: Run go vet - run: make vet - - - name: Run unit tests - env: - GO_BIN_PATH: ${{ env.GO_BIN_DIR }} - run: | - export PATH="$GO_BIN_PATH:$PATH" - make test - - - name: Build operator binary - run: make build - - - name: Check Go modules - run: | - go mod tidy - git diff --exit-code go.mod go.sum - - verify-manifests: - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Save Go bin directory to environment - run: | - GO_BIN_DIR=$(dirname $(which go)) - echo "GO_BIN_DIR=$GO_BIN_DIR" >> $GITHUB_ENV - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Verify generated manifests are up to date - env: - GO_BIN_PATH: ${{ env.GO_BIN_DIR }} - run: | - export PATH="$GO_BIN_PATH:$PATH" - make manifests - make addheaders - git diff --exit-code config/rbac/ config/crd/ - - cli-checks: - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.26' - cache: true - - - name: Copy .env configuration - run: cp .env.example .env - - - name: Run CLI unit tests - working-directory: cli - run: go test -v ./... - - - name: Build CLI - working-directory: cli - run: make build - - - name: Verify CLI binary works - working-directory: cli - run: ./dist/kn-workflow version diff --git a/.gitignore b/.gitignore index 3334f4e3..6639fed3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,11 @@ -# These files are generated by Cekit, we can ignore the operator-sdk ones. -bundle.Dockerfile -Dockerfile - -.DS_Store - # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib +bin/* +Dockerfile.cross # Test binary, built with `go test -c` *.test @@ -17,37 +13,16 @@ Dockerfile # Output of the go coverage tool, specifically when used with LiteIDE *.out -# Dependency directories (remove the comment below to include it) -# vendor/ -.idea -.vscode -*.iml - -/bin/ -/.idea/ -/.vscode/ -/target/ -/__debug* -database/ - -database/index.db -e2e-test-report*.xml -*.tar +# Go workspace file +go.work +# Kubernetes Generated files - skip generated files, except for vendored files +!vendor/**/zz_generated.* -## Auto-generated files -bundle/manifests/*.yaml -config/crd/bases/*.yaml - -# Local environment configuration -.env - -# Coverage output -cover.out - -# Vim swap files +# editor and IDE paraphernalia +.idea/* +!.idea/runConfigurations/ +.vscode *.swp *.swo - -# Python virtual environment -venv/ +*~ diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..5c78f833 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,55 @@ +version: "2" +run: + allow-parallel-runners: true +linters: + default: none + enable: + - copyloopvar + - dupl + - errcheck + - ginkgolinter + - goconst + - gocyclo + - govet + - ineffassign + - lll + - misspell + - nakedret + - prealloc + - revive + - staticcheck + - unconvert + - unparam + - unused + settings: + revive: + rules: + - name: comment-spacings + - name: import-shadowing + exclusions: + generated: lax + rules: + - linters: + - lll + path: api/* + - linters: + - dupl + - lll + path: internal/* + - linters: + - lll + path: utils/* + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/.idea/runConfigurations/Build_Manager.xml b/.idea/runConfigurations/Build_Manager.xml new file mode 100644 index 00000000..0af8aca7 --- /dev/null +++ b/.idea/runConfigurations/Build_Manager.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.idea/runConfigurations/Make_Build.xml b/.idea/runConfigurations/Make_Build.xml new file mode 100644 index 00000000..c44ab514 --- /dev/null +++ b/.idea/runConfigurations/Make_Build.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.idea/runConfigurations/Make_Test.xml b/.idea/runConfigurations/Make_Test.xml new file mode 100644 index 00000000..58f9aeb0 --- /dev/null +++ b/.idea/runConfigurations/Make_Test.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..c5eb38c1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,41 @@ +# Claude Code Instructions for Logic Operator + +## Git Workflow Rules + +**CRITICAL: You are NOT allowed to:** + +- ❌ Create git commits (`git commit`) without explicit user approval +- ❌ Push to remote branches (`git push`) without explicit user approval +- ❌ Create pull requests (`gh pr create`) without explicit user approval +- ❌ Force push (`git push --force`) under any circumstances +- ❌ Amend commits (`git commit --amend`) without explicit user approval + +**What you CAN do:** + +- ✅ Stage files with `git add` +- ✅ Check status with `git status`, `git diff` +- ✅ Create and switch branches +- ✅ Run tests and builds +- ✅ Read and edit files +- ✅ Provide commit message suggestions + +## Workflow + +When you complete work: + +1. Stage the changes with `git add` +2. Show `git status` and `git diff --staged` +3. **Suggest** a commit message +4. **STOP and wait** for user to review and commit + +The user will review changes and handle all git commits and pushes manually. + +## Exception + +Only create commits/PRs when the user **explicitly says**: +- "go ahead and commit" +- "please commit this" +- "create a PR" +- or similar explicit approval + +If in doubt, DO NOT commit. Ask first. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..cb1b130f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Build the manager binary +FROM golang:1.24 AS builder +ARG TARGETOS +ARG TARGETARCH + +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY cmd/main.go cmd/main.go +COPY api/ api/ +COPY internal/ internal/ + +# Build +# the GOARCH has not a default value to allow the binary be built according to the host where the command +# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO +# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, +# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. +RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go + +# Use distroless as minimal base image to package the manager binary +# Refer to https://github.com/GoogleContainerTools/distroless for more details +FROM gcr.io/distroless/static:nonroot +WORKDIR / +COPY --from=builder /workspace/manager . +USER 65532:65532 + +ENTRYPOINT ["/manager"] diff --git a/E2E_SETUP.md b/E2E_SETUP.md deleted file mode 100644 index c36937dc..00000000 --- a/E2E_SETUP.md +++ /dev/null @@ -1,220 +0,0 @@ -# E2E Test Setup for Logic Operator - -## Overview - -The Logic Operator e2e tests verify the complete operator functionality including workflow builds, deployments, and integrations with Knative and Prometheus. - -## Prerequisites - -### Required Tools -- `kubectl` -- `kind` (v0.20.0+) OR `minikube` -- `docker` or `podman` -- `go` (1.26.0+) -- `python3` with `cekit` (see hack/setup-cekit.sh) -- `make` - -### System Dependencies (for CEKit) -Ubuntu/Debian: -```bash -sudo apt-get install libxml2-dev libxslt-dev python3-dev libkrb5-dev -``` - -macOS: -```bash -brew install libxml2 libxslt krb5 -``` - -Fedora/RHEL: -```bash -sudo dnf install libxml2-devel libxslt-devel python3-devel krb5-devel -``` - -### Required Images -All images are hosted at `quay.io/kubesmarts` with tag `main`: -- `incubator-kie-sonataflow-builder:main` -- `incubator-kie-sonataflow-devmode:main` -- `incubator-kie-kogito-jobs-service-postgresql:main` -- `incubator-kie-kogito-jobs-service-ephemeral:main` -- `incubator-kie-kogito-data-index-postgresql:main` -- `incubator-kie-kogito-data-index-ephemeral:main` -- `incubator-kie-kogito-db-migrator:main` - -## Quick Start (KIND) - -The full e2e suite using KIND: - -```bash -# 1. Setup CEKit (one time) -./hack/setup-cekit.sh -source venv/bin/activate - -# 2. Pull test images -./hack/pull-test-images.sh - -# 3. Run full e2e suite -make full-test-e2e -``` - -This will: -1. Create a KIND cluster with local registry -2. Build and load the operator image -3. Load builder and devmode images -4. Deploy the operator -5. Install Knative Serving and Eventing -6. Install Prometheus -7. Run all e2e test suites: - - Platform tests - - Cluster platform tests - - Workflow monitoring tests - - Workflow persistence tests - - Workflow ephemeral tests - -## Alternative: Minikube - -For local development with Minikube: - -```bash -./hack/local/run-e2e.sh [profile] [skip-build] [test-label] [skip-undeploy] -``` - -Examples: -```bash -# Run platform tests with fresh build -./hack/local/run-e2e.sh minikube false platform false - -# Run ephemeral tests, skip build -./hack/local/run-e2e.sh minikube true flows-ephemeral false -``` - -## Test Labels - -- `platform` - SonataFlowPlatform deployment and configuration tests -- `cluster` - SonataFlowClusterPlatform tests -- `flows-ephemeral` - Workflow tests without persistence -- `flows-persistence` - Workflow tests with database persistence -- `flows-monitoring` - Workflow monitoring with Prometheus -- `flows-hpa` - Horizontal Pod Autoscaler tests -- `flows-pdb` - Pod Disruption Budget tests -- `flows-pdb-with-hpa` - Combined PDB and HPA tests - -## CI/CD Setup - -The repository includes GitHub Actions workflows in `.github/workflows/`: - -### E2E Tests Workflow (`.github/workflows/e2e.yaml`) - -Runs the full e2e test suite on every PR and push to main/master: - -1. Sets up Go 1.25 and Python -2. Installs CEKit in a Python venv -3. Pulls test images from quay.io/kubesmarts -4. Builds operator container image -5. Creates KIND cluster with local registry -6. Loads images into KIND -7. Deploys operator, Knative, and Prometheus -8. Runs all e2e test suites: - - platform - - cluster - - flows-monitoring - - flows-persistence - - flows-ephemeral -9. Collects logs and test results on failure -10. Uploads test artifacts - -**Trigger:** Pull requests and pushes to main/master, or manual via `workflow_dispatch` - -### PR Checks Workflow (`.github/workflows/pr-checks.yaml`) - -Fast checks for pull requests: - -1. **lint-and-test job:** - - Go fmt check - - Go vet - - Unit tests - - Build operator binary - - Verify Go modules are tidy - -2. **verify-manifests job:** - - Verify generated manifests are up to date - - Verify CRD bundle is up to date - -**Trigger:** Pull requests only - -These workflows use the existing Makefile targets, so local development and CI use the same build/test commands - -### Faster CI Option: Unit Tests Only - -For quick PR checks, run only unit tests: - -```yaml -- name: Run unit tests - run: make test -``` - -## Build System - -The operator uses **CEKit** (Container Evolution Kit) for building container images. CEKit must be installed in a Python virtual environment: - -```bash -# One-time setup -python3 -m venv venv -source venv/bin/activate -pip install -r images/requirements.txt -``` - -Add `venv/bin/activate` sourcing to your build scripts. - -## Workflow Builds in Tests - -The e2e tests use **Kaniko** to build workflow containers inside the cluster. The BeforeSuite: - -1. Creates `e2e-resources` namespace -2. Deploys sample workflows -3. Creates a SonataFlowPlatform with Kaniko configuration -4. Waits for workflows to build into container images -5. Extracts built image tags -6. Scales workflows to 0 (images cached in local registry) -7. Individual tests deploy workflows using pre-built images - -This requires: -- A container registry accessible from the cluster (KIND local registry or Minikube registry addon) -- Builder images loaded into the cluster -- Kaniko build cache enabled in the platform - -## Troubleshooting - -### CEKit not found -```bash -source venv/bin/activate -``` - -### Image pull failures -Check that `.env` file exists with correct image references: -```bash -cp .env.example .env -``` - -### KIND kube-proxy errors -Usually safe to ignore if nodes show Ready. May indicate local file descriptor limits. - -### Workflow builds not starting -Ensure Son ataFlowPlatform exists in the test namespace with Kaniko configuration: -```yaml -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" -``` - -## Clean Up - -```bash -# Delete KIND cluster -make delete-cluster - -# Clean test namespaces -kubectl delete namespace e2e-resources -kubectl get namespaces | grep test- | awk '{print $1}' | xargs kubectl delete namespace -``` diff --git a/MIGRATION.md b/MIGRATION.md deleted file mode 100644 index ac4aec18..00000000 --- a/MIGRATION.md +++ /dev/null @@ -1,65 +0,0 @@ -# Migration from SonataFlow Operator - -This repository is a continuation of the Apache KIE SonataFlow Operator, migrated from the -[Apache KIE Tools monorepo](https://github.com/apache/incubator-kie-tools) to a standalone -repository. - -## What Changed - -### Repository Location -- **Old:** `github.com/apache/incubator-kie-tools/packages/sonataflow-operator` -- **New:** `github.com/kubesmarts/logic-operator` - -### Go Module Paths -All import paths have been updated: -```go -// Old -import "github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api/v1alpha08" - -// New -import "github.com/kubesmarts/logic-operator/api/v1alpha08" -``` - -### Build System -- **Removed:** pnpm/npm dependencies and build-env configuration -- **Added:** `.env` file-based configuration -- **Simplified:** Pure Go/Make build system - -### Configuration -Copy `.env.example` to `.env` and customize: -```bash -cp .env.example .env -``` - -Set environment variables to override defaults: -```bash -export VERSION=2.0.1 -export REGISTRY=quay.io -make build -``` - -## Git History - -The full commit history from the monorepo has been preserved. All commits that touched -the `packages/sonataflow-operator` directory are included with paths rewritten to the -repository root. - -Original migration commit: `v2.0.0-migration-base` - -## License - -This project maintains the Apache License 2.0 from the original project. All existing -files retain their original Apache Software Foundation copyright headers. New files -contributed after the migration use Kubesmarts copyright headers. - -## For Existing Users - -If you were using the operator from the monorepo: - -1. Update your Go module imports to `github.com/kubesmarts/logic-operator` -2. Run `go mod tidy` to update dependencies -3. No changes to CRDs or runtime behavior - full compatibility maintained - -## Migration Date - -Migration completed: June 18, 2026 diff --git a/Makefile b/Makefile index 0ae94f14..83472d34 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,9 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Load .env file if it exists, allowing environment variables to override -ifneq (,$(wildcard .env)) - include .env - export -endif - # VERSION defines the project version for the bundle. # Update this value when you upgrade the version of your project. # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 2.0.0-snapshot -IMAGE_TAG ?= 2.0.0 +VERSION ?= 0.0.1 # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") @@ -48,61 +24,52 @@ BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) -# IMAGE_TAG_BASE defines the image namespace and part of the image name for remote images. +# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. # This variable is used to construct full image tags for bundle and catalog images. # # For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both -# apache/sonataflow-operator-bundle:$VERSION and apache/sonataflow-operator-catalog:$VERSION. -REGISTRY ?= quay.io -ACCOUNT ?= kiegroup -OPERATOR_NAME ?= logic-operator -IMAGE_TAG_BASE ?= $(REGISTRY)/$(ACCOUNT)/$(OPERATOR_NAME) +# kubesmarts.org/logic-operator-bundle:$VERSION and kubesmarts.org/logic-operator-catalog:$VERSION. +IMAGE_TAG_BASE ?= kubesmarts.org/logic-operator # BUNDLE_IMG defines the image:tag used for the bundle. # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) -BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:$(IMAGE_TAG) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) # BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command -# TODO: review this flag once we upgrade https://github.com/operator-framework/operator-sdk/issues/4992 (https://issues.redhat.com/browse/KOGITO-9428) -# TODO: It is preventing us from adding new annotations to bundle/metadata/annotations.yaml -BUNDLE_GEN_FLAGS ?= -q --overwrite=false --version $(VERSION) $(BUNDLE_METADATA_OPTS) - -# Container runtime engine used for building the images -BUILDER ?= docker +BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) # USE_IMAGE_DIGESTS defines if images are resolved via tags or digests # You can enable this value if you would like to use SHA Based Digests # To enable set flag to true -IMG_TAG_SEP = : USE_IMAGE_DIGESTS ?= false ifeq ($(USE_IMAGE_DIGESTS), true) BUNDLE_GEN_FLAGS += --use-image-digests - IMG_TAG_SEP = @ endif +# Set the Operator SDK version to use. By default, what is installed on the system is used. +# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. +OPERATOR_SDK_VERSION ?= v1.42.2 # Image URL to use all building/pushing image targets -IMG ?= $(IMAGE_TAG_BASE)$(IMG_TAG_SEP)$(IMAGE_TAG) -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.26 - -OPERATOR_SDK_VERSION ?= v1.35.0 +IMG ?= controller:latest # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) -ifeq (,$(shell go env GOBIN 2>/dev/null)) -GOBIN=$(shell go env GOPATH 2>/dev/null || echo $(HOME)/go)/bin +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin else -GOBIN=$(shell go env GOBIN 2>/dev/null) +GOBIN=$(shell go env GOBIN) endif +# CONTAINER_TOOL defines the container tool to be used for building images. +# Be aware that the target commands are only tested with Docker which is +# scaffolded by default. However, you might want to replace it to use other +# tools. (i.e. podman) +CONTAINER_TOOL ?= docker + # Setting SHELL to bash allows bash commands to be executed by recipes. -# This is a requirement for 'setup-envtest.sh' in the test target. # Options are set to exit when a recipe line exits non-zero or a piped command fails. SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec -# Export all variables to subprocesses (needed for controller-gen to find go) -.EXPORT_ALL_VARIABLES: - .PHONY: all all: build @@ -110,7 +77,7 @@ all: build # The help target prints out all targets with their descriptions organized # beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the +# target descriptions by '##'. The awk command is responsible for reading the # entire set of makefiles included in this invocation, looking for lines of the # file as xyz: ## something, and then pretty-format the target and help. Then, # if there's a line with ##@ something, that gets pretty-printed as a category. @@ -126,47 +93,53 @@ help: ## Display this help. ##@ Development .PHONY: manifests -manifests: generate ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - @echo "📄 Generating WebhookConfiguration, ClusterRole, and CRD objects..." - @$(CONTROLLER_GEN) rbac:roleName=manager-role crd:allowDangerousTypes=true webhook paths="./api/..." paths="./internal/controller/..." output:crd:artifacts:config=config/crd/bases +manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./api/..." paths="./cmd/..." paths="./internal/..." output:crd:artifacts:config=config/crd/bases .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - @echo "🔄 Generating DeepCopy methods for APIs..." - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..." paths="./container-builder/api/..." - @echo "🧹 Formatting generated files..." - @gofmt -s -w api/zz_generated.deepcopy.go container-builder/api/zz_generated.deepcopy.go + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..." paths="./cmd/..." paths="./internal/..." .PHONY: fmt fmt: ## Run go fmt against code. - @echo "🧹 Running go fmt and goimports..." - @./hack/goimports.sh > /dev/null 2>&1 - @go work sync > /dev/null 2>&1 - @go mod tidy > /dev/null 2>&1 - @go fmt ./... > /dev/null 2>&1 + go fmt ./... .PHONY: vet vet: ## Run go vet against code. - @echo "🔍 Running go vet..." - @go vet ./... + go vet ./... .PHONY: test -test: manifests generate test-api ## Run tests. - @$(MAKE) addheaders - @$(MAKE) vet - @$(MAKE) fmt - @echo "🔍 Running controller tests..." - @# Only run coverage on packages that have test files to avoid Go 1.26 covdata tool issue - @go test $(shell go list -f '{{if .TestGoFiles}}{{.ImportPath}}{{end}}' ./... | grep -v /test/) -coverprofile cover.out || \ - go test $(shell go list ./... | grep -v /test/) - @echo "✅ Tests completed successfully." - -.PHONY: test-api -test-api: - @echo "🔄 Running API tests..." - @cd api && make test > /dev/null 2>&1 - @echo "✅ API tests completed successfully." - +test: manifests generate fmt vet setup-envtest ## Run tests. + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out + +# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'. +# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally. +# CertManager is installed by default; skip with: +# - CERT_MANAGER_INSTALL_SKIP=true +KIND_CLUSTER ?= logic-operator-test-e2e + +.PHONY: setup-test-e2e +setup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist + @command -v $(KIND) >/dev/null 2>&1 || { \ + echo "Kind is not installed. Please install Kind manually."; \ + exit 1; \ + } + @case "$$($(KIND) get clusters)" in \ + *"$(KIND_CLUSTER)"*) \ + echo "Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation." ;; \ + *) \ + echo "Creating Kind cluster '$(KIND_CLUSTER)'..."; \ + $(KIND) create cluster --name $(KIND_CLUSTER) ;; \ + esac + +.PHONY: test-e2e +test-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind. + KIND_CLUSTER=$(KIND_CLUSTER) go test ./test/e2e/ -v -ginkgo.v + $(MAKE) cleanup-test-e2e + +.PHONY: cleanup-test-e2e +cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests + @$(KIND) delete cluster --name $(KIND_CLUSTER) .PHONY: lint lint: golangci-lint ## Run golangci-lint linter @@ -176,73 +149,53 @@ lint: golangci-lint ## Run golangci-lint linter lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes $(GOLANGCI_LINT) run --fix -###### -# Test proxy commands - -TEST_DIR=testbdd - -.PHONY: run-tests -run-tests: generate-all - @(cd $(TEST_DIR) && $(MAKE) $@) - -.PHONY: run-smoke-tests -run-smoke-tests: generate-all - @(cd $(TEST_DIR) && $(MAKE) $@) - -.PHONY: test-container-builder -test-container-builder: - cd container-builder && make test - -.PHONY: test-workflowproj -test-workflowproj: - cd workflowproj && make test +.PHONY: lint-config +lint-config: golangci-lint ## Verify golangci-lint linter configuration + $(GOLANGCI_LINT) config verify ##@ Build .PHONY: build -build: ## Build manager binary. - CGO_ENABLED=0 go build -trimpath -ldflags=-buildid= -o bin/manager cmd/main.go - -.PHONY: build-4-debug -build-4-debug: generate ## Build manager binary with debug options. - go build -gcflags="all=-N -l" -o bin/manager cmd/main.go +build: manifests generate fmt vet ## Build manager binary. + go build -o bin/manager cmd/main.go .PHONY: run -run: manifests generate ## Run a controller from your host. - go run ./cmd/main.go -v=2 -controller-cfg-path=$(CURDIR)/config/manager/controllers_cfg.yaml +run: manifests generate fmt vet ## Run a controller from your host. + go run ./cmd/main.go + +# If you wish to build the manager image targeting other platforms you can use the --platform flag. +# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. +# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +.PHONY: docker-build +docker-build: ## Build docker image with the manager. + $(CONTAINER_TOOL) build -t ${IMG} . -.PHONY: debug -debug: build-4-debug ## Run a controller from your host from binary - ./bin/manager -v=2 -controller-cfg-path=$(CURDIR)/config/manager/controllers_cfg.yaml +.PHONY: docker-push +docker-push: ## Push docker image with the manager. + $(CONTAINER_TOOL) push ${IMG} -# This is currently done directly into the CI -# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple +# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple # architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ -# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> than the export will fail) -# To properly provided solutions that supports more than one platform you should use this option. +# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/ +# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=> then the export will fail) +# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option. PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le .PHONY: docker-buildx -docker-buildx: generate ## Build and push docker image for the manager for cross-platform support +docker-buildx: ## Build and push docker image for the manager for cross-platform support # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - - docker buildx create --name project-v3-builder - docker buildx use project-v3-builder - - docker buildx build --build-arg SOURCE_DATE_EPOCH=$(shell git log -1 --pretty=%ct) --push . --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross - - docker buildx rm project-v3-builder + - $(CONTAINER_TOOL) buildx create --name logic-operator-builder + $(CONTAINER_TOOL) buildx use logic-operator-builder + - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross . + - $(CONTAINER_TOOL) buildx rm logic-operator-builder rm Dockerfile.cross -.PHONY: container-build -container-build: ## Build the container image - cekit -v --descriptor images/manager.yaml build ${build_options} $(BUILDER) --no-squash --build-arg SOURCE_DATE_EPOCH="$(shell git log -1 --pretty=%ct)" -ifneq ($(ignore_tag),true) - $(BUILDER) tag sonataflow-operator:latest ${IMG} -endif - -.PHONY: container-push -container-push: ## Push the container image - $(BUILDER) push ${CONTAINER_PUSH_PARAMS} ${IMG} +.PHONY: build-installer +build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment. + mkdir -p dist + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default > dist/install.yaml ##@ Deployment @@ -252,35 +205,22 @@ endif .PHONY: install install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | kubectl create -f - + $(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f - .PHONY: uninstall uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - + $(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - .PHONY: deploy deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl create -f - - -.PHONY: deploy-only -deploy-only: kustomize ## Deploy controller without regenerating manifests (use when manifests are already generated) - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl create -f - - -.PHONY: generate-deploy -generate-deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. - @echo "🚀 Updating controller image to ${IMG}..." - @cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} > /dev/null 2>&1 - @echo "📄 Building deployment YAML..." - @$(KUSTOMIZE) build config/default > operator.yaml - + $(KUSTOMIZE) build config/default | $(KUBECTL) apply -f - .PHONY: undeploy -undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f - +undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. + $(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - -##@ Build Dependencies +##@ Dependencies ## Location to install dependencies to LOCALBIN ?= $(shell pwd)/bin @@ -289,26 +229,20 @@ $(LOCALBIN): ## Tool Binaries KUBECTL ?= kubectl -KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION) +KIND ?= kind +KUSTOMIZE ?= $(LOCALBIN)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION) -GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION) +ENVTEST ?= $(LOCALBIN)/setup-envtest +GOLANGCI_LINT = $(LOCALBIN)/golangci-lint ## Tool Versions -KUSTOMIZE_VERSION ?= v5.4.1 -CONTROLLER_TOOLS_VERSION ?= v0.16.4 -ENVTEST_VERSION ?= release-0.18 -GOLANGCI_LINT_VERSION ?= v1.57.2 - -KIND_VERSION ?= v0.20.0 -KNATIVE_VERSION ?= v1.13.2 -TIMEOUT_SECS ?= 180s -PROMETHEUS_VERSION ?= v0.70.0 -GRAFANA_VERSION ?= v5.13.0 - -KNATIVE_SERVING_PREFIX ?= "https://github.com/knative/serving/releases/download/knative-$(KNATIVE_VERSION)" -KNATIVE_EVENTING_PREFIX ?= "https://github.com/knative/eventing/releases/download/knative-$(KNATIVE_VERSION)" -KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" +KUSTOMIZE_VERSION ?= v5.6.0 +CONTROLLER_TOOLS_VERSION ?= v0.18.0 +#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20) +ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}') +#ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31) +ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}') +GOLANGCI_LINT_VERSION ?= v2.1.0 .PHONY: kustomize kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. @@ -317,11 +251,16 @@ $(KUSTOMIZE): $(LOCALBIN) .PHONY: controller-gen controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. - @echo "⬇️ Ensuring controller-gen is installed..." - @test -s $(CONTROLLER_GEN) || (GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) > /dev/null 2>&1 && echo "✅ controller-gen installed successfully!") - -$(CONTROLLER_GEN): - @mkdir -p $(LOCALBIN) # Ensure LOCALBIN exists +$(CONTROLLER_GEN): $(LOCALBIN) + $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION)) + +.PHONY: setup-envtest +setup-envtest: envtest ## Download the binaries required for ENVTEST in the local bin directory. + @echo "Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)..." + @$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \ + echo "Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION)."; \ + exit 1; \ + } .PHONY: envtest envtest: $(ENVTEST) ## Download setup-envtest locally if necessary. @@ -331,49 +270,58 @@ $(ENVTEST): $(LOCALBIN) .PHONY: golangci-lint golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) - $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION}) + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION)) # go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist -# $1 - target path with name of binary (ideally with version) +# $1 - target path with name of binary # $2 - package url which can be installed # $3 - specific version of package define go-install-tool -@[ -f $(1) ] || { \ +@[ -f "$(1)-$(3)" ] || { \ set -e; \ package=$(2)@$(3) ;\ echo "Downloading $${package}" ;\ +rm -f $(1) || true ;\ GOBIN=$(LOCALBIN) go install $${package} ;\ -mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\ -} +mv $(1) $(1)-$(3) ;\ +} ;\ +ln -sf $(1)-$(3) $(1) endef +.PHONY: operator-sdk +OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk +operator-sdk: ## Download operator-sdk locally if necessary. +ifeq (,$(wildcard $(OPERATOR_SDK))) +ifeq (, $(shell which operator-sdk 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(OPERATOR_SDK)) ;\ + OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ + curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\ + chmod +x $(OPERATOR_SDK) ;\ + } +else +OPERATOR_SDK = $(shell which operator-sdk) +endif +endif .PHONY: bundle -PACKAGE_NAME = "sonataflow-operator" -bundle: manifests kustomize install-operator-sdk ## Generate bundle manifests and metadata, then validate generated files. - @echo "📦 Generating bundle manifests and metadata..." - @operator-sdk generate kustomize manifests --package=$(PACKAGE_NAME) -q > /dev/null 2>&1 - @echo "🔧 Setting controller image in Kustomize..." - @cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) > /dev/null 2>&1 - @echo "🔨 Building Kustomize and generating bundle..." - @$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle $(BUNDLE_GEN_FLAGS) --package=$(PACKAGE_NAME) > /dev/null 2>&1 - @echo "🛠️ Validating generated bundle..." - @operator-sdk bundle validate ./bundle > /dev/null 2>&1 +bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + $(OPERATOR_SDK) bundle validate ./bundle .PHONY: bundle-build -BUNDLE_DESCRIPTOR = "images/bundle.yaml" -bundle-build: ## Build the bundle image - cekit -v --descriptor $(BUNDLE_DESCRIPTOR) build ${build_options} $(BUILDER) --no-squash --platform=linux/amd64 --build-arg SOURCE_DATE_EPOCH="$(shell git log -1 --pretty=%ct)" -ifneq ($(ignore_tag),true) - $(BUILDER) tag sonataflow-operator-bundle:latest $(BUNDLE_IMG) -endif +bundle-build: ## Build the bundle image. + $(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) . .PHONY: bundle-push bundle-push: ## Push the bundle image. - $(MAKE) container-push IMG=$(BUNDLE_IMG) + $(MAKE) docker-push IMG=$(BUNDLE_IMG) .PHONY: opm -OPM = ./bin/opm +OPM = $(LOCALBIN)/opm opm: ## Download opm locally if necessary. ifeq (,$(wildcard $(OPM))) ifeq (,$(shell which opm 2>/dev/null)) @@ -381,7 +329,7 @@ ifeq (,$(shell which opm 2>/dev/null)) set -e ;\ mkdir -p $(dir $(OPM)) ;\ OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ - curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v$(OPERATOR_SDK_VERSION)/$${OS}-$${ARCH}-opm ;\ + curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\ chmod +x $(OPM) ;\ } else @@ -394,169 +342,21 @@ endif BUNDLE_IMGS ?= $(BUNDLE_IMG) # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). -CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:$(IMAGE_TAG) +CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) # Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif -PLATFORM ?= linux/amd64 - # Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator .PHONY: catalog-build catalog-build: opm ## Build a catalog image. - $(OPM) index add --container-tool $(BUILDER) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) --generate -d ./index.Dockerfile - $(BUILDER) build --platform $(PLATFORM) -f ./index.Dockerfile -t $(CATALOG_IMG) . - rm ./index.Dockerfile + $(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) # Push the catalog image. .PHONY: catalog-push catalog-push: ## Push a catalog image. - $(MAKE) container-push IMG=$(CATALOG_IMG) - -.PHONY: clean -clean: - rm -rf bin/ - -.PHONY: bump-version -new_version = "" -bump-version: - ./hack/bump-version.sh $(new_version) - -.PHONY: install-operator-sdk -install-operator-sdk: - @echo "📦 Installing Operator SDK..." - @./hack/install-operator-sdk.sh - - -.PHONY: addheaders -addheaders: - @echo "📝 Adding headers to files..." - @./hack/addheaders.sh > /dev/null 2>&1 - -.PHONY: generate-all -generate-all: generate generate-deploy bundle - @$(MAKE) addheaders - @$(MAKE) vet - @$(MAKE) fmt - -.PHONY: test-e2e # You will need to have a Minikube/Kind cluster up and running to run this target, and run container-builder before the test -label = "flows-ephemeral" # possible values are flows-ephemeral, flows-persistence, flows-monitoring, flows-hpa, flows-pdb-with-hpa, flows-pdb, platform, cluster -test-e2e: -ifeq ($(label), cluster) - @echo "🌐 Running e2e tests for cluster..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/clusterplatform_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-clusterplatform_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), platform) - @echo "📦 Running e2e tests for platform..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/platform_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-platform_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-ephemeral) - @echo "🔄 Running e2e tests for flows-ephemeral..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-persistence) - @echo "🔁 Running e2e tests for flows-persistence..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-monitoring) - @echo "🔁 Running e2e tests for flows-monitoring..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-hpa) - @echo "🔁 Running e2e tests for flows-hpa..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-pdb) - @echo "🔁 Running e2e tests for flows-pdb..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else ifeq ($(label), flows-pdb-with-hpa) - @echo "🔁 Running e2e tests for flows-pdb-with-hpa..." - go test ./test/e2e/e2e_suite_test.go ./test/e2e/helpers.go ./test/e2e/workflow_test.go \ - -v -ginkgo.v -ginkgo.no-color -ginkgo.github-output -ginkgo.label-filter=$(label) \ - -ginkgo.junit-report=./e2e-test-report-workflow_test.xml -timeout 60m KUSTOMIZE=$(KUSTOMIZE); -else - @echo "❌ Invalid label. Please use one of: cluster, platform, flows-ephemeral, flows-persistence, flows-monitoring, flows-hpa, flows-pdb, flows-pdb-with-hpa" -endif - -.PHONY: full-test-e2e -full-test-e2e: create-cluster load-docker-image deploy deploy-knative deploy-prometheus - sleep 30 - kubectl wait pod -A -l app.kubernetes.io/name=sonataflow-operator --for condition=Ready --timeout 120s - @$(MAKE) test-e2e label=platform - @$(MAKE) test-e2e label=cluster - @$(MAKE) test-e2e label=flows-monitoring - @$(MAKE) test-e2e label=flows-persistence - @$(MAKE) test-e2e label=flows-ephemeral - -.PHONY: before-pr -before-pr: generate-all test ## Run generate-all before executing tests. - @echo "✅ Your working branch is done." - -.PHONY: load-docker-image -load-docker-image: install-kind - kind load docker-image $(IMG) - -.PHONY: install-kind -install-kind: - command -v kind >/dev/null || go install sigs.k8s.io/kind@$(KIND_VERSION) - -.PHONY: create-cluster -create-cluster: install-kind - kind get clusters | grep kind >/dev/null || ./hack/create-kind-cluster-with-registry.sh $(BUILDER) - -.PHONY: deploy-knative -deploy-knative: - kubectl apply -f https://github.com/knative/operator/releases/download/knative-$(KNATIVE_VERSION)/operator.yaml - kubectl wait --for=condition=Available=True deploy/knative-operator -n default --timeout=$(TIMEOUT_SECS) - kubectl apply -f ./test/testdata/knative_serving_eventing.yaml - kubectl wait --for=condition=Ready=True KnativeServing/knative-serving -n knative-serving --timeout=$(TIMEOUT_SECS) - kubectl wait --for=condition=Ready=True KnativeEventing/knative-eventing -n knative-eventing --timeout=$(TIMEOUT_SECS) - -.PHONY: deploy-prometheus -deploy-prometheus: create-cluster - kubectl create -f https://github.com/prometheus-operator/prometheus-operator/releases/download/$(PROMETHEUS_VERSION)/bundle.yaml - kubectl wait --for=condition=Available=True deploy/prometheus-operator -n default --timeout=$(TIMEOUT_SECS) - kubectl apply -f ./test/testdata/prometheus.yaml -n default - kubectl wait --for=condition=Available=True prometheus/prometheus -n default --timeout=$(TIMEOUT_SECS) - -.PHONY: deploy-grafana -deploy-grafana: create-cluster - kubectl create -f https://github.com/grafana/grafana-operator/releases/download/$(GRAFANA_VERSION)/kustomize-cluster_scoped.yaml - kubectl wait --for=condition=Available=True deploy/grafana-operator-controller-manager -n grafana --timeout=$(TIMEOUT_SECS) - -.PHONY: delete-cluster -delete-cluster: install-kind - kind delete cluster && $(BUILDER) rm -f kind-registry - -# Updates the manager_env_patch.yaml file with the images used by the operator. -# These params come from the .env file or environment variables -.PHONY: update-patch -update-patch: - @echo "🔧 Updating Kustomize patch file..." - $(eval PARAMS := \ - RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL=$(RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL) \ - RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL=$(RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL) \ - RELATED_IMAGE_DATA_INDEX_POSTGRESQL=$(RELATED_IMAGE_DATA_INDEX_POSTGRESQL) \ - RELATED_IMAGE_DATA_INDEX_EPHEMERAL=$(RELATED_IMAGE_DATA_INDEX_EPHEMERAL) \ - RELATED_IMAGE_BASE_BUILDER=$(RELATED_IMAGE_BASE_BUILDER) \ - RELATED_IMAGE_DEVMODE=$(RELATED_IMAGE_DEVMODE) \ - RELATED_IMAGE_DB_MIGRATOR_TOOL=$(RELATED_IMAGE_DB_MIGRATOR_TOOL)) - @if [ -z "$(strip $(PARAMS))" ]; then \ - echo "⚠️ No variables resolved. Skipping updates."; \ - else \ - echo "✅ Resolved:"; echo "$(PARAMS)" | tr ' ' '\n'; \ - python ./hack/update_patch_env.py "$(PIN_IMAGE_SHA_BUNDLE_TOOL)" $(PARAMS); \ - echo "✅ Patch updated!"; \ - fi + $(MAKE) docker-push IMG=$(CATALOG_IMG) diff --git a/PROJECT b/PROJECT index 64657083..97c3e313 100644 --- a/PROJECT +++ b/PROJECT @@ -1,45 +1,50 @@ -domain: org +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html +domain: kubesmarts.org layout: - go.kubebuilder.io/v4 plugins: manifests.sdk.operatorframework.io/v2: {} scorecard.sdk.operatorframework.io/v2: {} -projectName: sonataflow-operator -repo: github.com/apache/incubator-kie-tools/packages/sonataflow-operator +projectName: logic-operator +repo: github.com/kubesmarts/logic-operator resources: - api: crdVersion: v1 namespaced: true controller: true - domain: org - group: sonataflow - kind: SonataFlow - path: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api/v1alpha08 - version: v1alpha08 + domain: kubesmarts.org + group: logic + kind: LogicPlatform + path: github.com/kubesmarts/logic-operator/api/v1 + version: v1 - api: crdVersion: v1 namespaced: true controller: true - domain: org - group: sonataflow - kind: SonataFlowBuild - path: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api/v1alpha08 - version: v1alpha08 + domain: kubesmarts.org + group: logic + kind: LogicFlowService + path: github.com/kubesmarts/logic-operator/api/v1 + version: v1 - api: crdVersion: v1 namespaced: true controller: true - domain: org - group: sonataflow - kind: SonataFlowPlatform - path: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api/v1alpha08 - version: v1alpha08 + domain: kubesmarts.org + group: logic + kind: LogicFlowDefinition + path: github.com/kubesmarts/logic-operator/api/v1 + version: v1 - api: crdVersion: v1 + namespaced: true controller: true - domain: org - group: sonataflow - kind: SonataFlowClusterPlatform - path: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api/v1alpha08 - version: v1alpha08 + domain: kubesmarts.org + group: logic + kind: LogicFlowRuntime + path: github.com/kubesmarts/logic-operator/api/v1 + version: v1 version: "3" diff --git a/README.md b/README.md index 34b07f69..19503edd 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,154 @@ - - # Logic Operator -[![E2E Tests](https://github.com/kubesmarts/logic-operator/actions/workflows/e2e.yaml/badge.svg)](https://github.com/kubesmarts/logic-operator/actions/workflows/e2e.yaml) -[![PR Checks](https://github.com/kubesmarts/logic-operator/actions/workflows/pr-checks.yaml/badge.svg)](https://github.com/kubesmarts/logic-operator/actions/workflows/pr-checks.yaml) +A Kubernetes operator for managing serverless logic workflows powered by Quarkus Flow. + +## Description + +The Logic Operator provides a Kubernetes-native way to deploy, manage, and scale serverless logic workflows. Built on top of Quarkus Flow, it offers four core CRDs for defining and orchestrating workflow-based applications: + +- **LogicPlatform**: Platform-wide configuration and shared services +- **LogicFlowService**: Service definitions for workflow deployments +- **LogicFlowDefinition**: Workflow definitions and specifications +- **LogicFlowRuntime**: Runtime instances of deployed workflows + +This is v2.0 of the operator, representing a complete architectural overhaul with modern Kubernetes patterns and improved scalability + +## Getting Started + +### Prerequisites +- go version v1.26.0+ +- docker version 17.03+ +- kubectl version v1.11.3+ +- Access to a Kubernetes v1.11.3+ cluster -The Logic Operator is a Kubernetes operator for deploying and managing serverless workflow applications. -It defines a set of [Kubernetes Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) -to help users deploy workflow projects on Kubernetes and OpenShift. +### To Deploy on the cluster +**Build and push your image to the location specified by `IMG`:** -This operator is a continuation of the Apache KIE SonataFlow Operator, maintained by Kubesmarts. +```sh +make docker-build docker-push IMG=/logic-operator:tag +``` + +**NOTE:** This image ought to be published in the personal registry you specified. +And it is required to have access to pull the image from the working environment. +Make sure you have the proper permission to the registry if the above commands don’t work. -## Documentation +**Install the CRDs into the cluster:** -For detailed documentation, please visit [the official documentation](https://kiegroup.github.io/kogito-docs/serverlessworkflow/latest/cloud/operator/install-serverless-operator.html). +```sh +make install +``` -## Available modules for integrations +**Deploy the Manager to the cluster with the image specified by `IMG`:** -If you're a developer, and you are interested in integrating your project or application with the SonataFlow Operator -ecosystem, this repository provides a few Go Modules described below. +```sh +make deploy IMG=/logic-operator:tag +``` -### SonataFlow Operator Types (api) +> **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin +privileges or be logged in as admin. -Every custom resource managed by the operator is exported in the module [api](api). You can use it to programmatically -create any custom type managed by the operator. -To use it, simply run: +**Create instances of your solution** +You can apply the samples (examples) from the config/sample: -```shell -go get github.com/kubesmarts/logic-operator/api +```sh +kubectl apply -k config/samples/ ``` -Then you can create any type programmatically, for example: +>**NOTE**: Ensure that the samples has default values to test it out. -```go -import ( - "github.com/kubesmarts/logic-operator/api/v1alpha08" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) +### To Uninstall +**Delete the instances (CRs) from the cluster:** -workflow := &v1alpha08.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{Name: w.name, Namespace: w.namespace}, - Spec: v1alpha08.SonataFlowSpec{Flow: *myWorkflowDef}, -} +```sh +kubectl delete -k config/samples/ ``` -You can use the [Kubernetes client-go library](https://github.com/kubernetes/client-go) to manipulate these objects in -the cluster. +**Delete the APIs(CRDs) from the cluster:** -You might need to register our schemes: +```sh +make uninstall +``` + +**UnDeploy the controller from the cluster:** -```go - s := scheme.Scheme -utilruntime.Must(v1alpha08.AddToScheme(s)) +```sh +make undeploy ``` -### Container Builder (container-builder) +## Project Distribution + +Following the options to release and provide this solution to the users. -Please see the module's [README file](container-builder/README.md). +### By providing a bundle with all YAML files -### Workflow Project Handler (workflowproj) +1. Build the installer for the image built and published in the registry: -Please see the module's [README file](workflowproj/README.md). +```sh +make build-installer IMG=/logic-operator:tag +``` + +**NOTE:** The makefile target mentioned above generates an 'install.yaml' +file in the dist directory. This file contains all the resources built +with Kustomize, which are necessary to install this project without its +dependencies. -## Build Requirements +2. Using the installer -To build and develop the Logic Operator, you need: +Users can just run 'kubectl apply -f ' to install +the project, i.e.: -- **Go** 1.25.0 or later -- **Make** -- **Python 3** with `ruamel.yaml` package -- **Node.js** (for `replace-in-file` utility used in version bumping) -- **Docker** or **Podman** (for container builds) -- Optional: **kubectl**, **kind** (for local testing) +```sh +kubectl apply -f https://raw.githubusercontent.com//logic-operator//dist/install.yaml +``` -### Configuration +### By providing a Helm Chart -The operator uses a `.env` file for build configuration. Copy the example file: +1. Build the chart using the optional helm plugin -```bash -cp .env.example .env +```sh +operator-sdk edit --plugins=helm/v1-alpha ``` -Edit `.env` to customize version numbers, registry locations, and image references. -All values can be overridden by environment variables. +2. See that a chart was generated under 'dist/chart', and users +can obtain this solution from there. + +**NOTE:** If you change the project, you need to update the Helm Chart +using the same command above to sync the latest changes. Furthermore, +if you create webhooks, you need to use the above command with +the '--force' flag and manually ensure that any custom configuration +previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml' +is manually re-applied afterwards. + +## Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Make your changes following the existing code style +4. Run tests: `make test` +5. Run linter: `make lint` +6. Submit a pull request + +For major changes, please open an issue first to discuss what you would like to change + +**NOTE:** Run `make help` for more information on all potential `make` targets + +More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html) + +## License + +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 -## Development and Contributions +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. -Contributing is easy, just take a look at our [contributors](https://github.com/kubesmarts/logic-operator/blob/main/docs/CONTRIBUTING.md) guide. diff --git a/api/Makefile b/api/Makefile deleted file mode 100644 index ea77583b..00000000 --- a/api/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -.PHONY: test -test: - @go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out 2>/dev/null || go test $(shell go list ./... | grep -v /test/) diff --git a/api/go.mod b/api/go.mod deleted file mode 100644 index 5b109d53..00000000 --- a/api/go.mod +++ /dev/null @@ -1,75 +0,0 @@ -module github.com/kubesmarts/logic-operator/api - -go 1.26.0 - -require ( - github.com/serverlessworkflow/sdk-go/v2 v2.5.0 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c - sigs.k8s.io/controller-runtime v0.19.0 - sigs.k8s.io/yaml v1.4.0 -) - -require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/relvacode/iso8601 v1.4.0 // indirect - github.com/sosodev/duration v1.3.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/x448/float16 v0.8.4 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/time v0.5.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/client-go v0.31.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect -) diff --git a/api/go.sum b/api/go.sum deleted file mode 100644 index fe3ff947..00000000 --- a/api/go.sum +++ /dev/null @@ -1,221 +0,0 @@ -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXUJs= -github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0 h1:bvD461rbaj0PcRjRwsBt7tqHie2M10otryB+BjzHg5Q= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0/go.mod h1:kuvTQCTAb9vzDaeJ1JPY+sBGiHr9OX1g/Rxuk82c8mI= -github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= -github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c/go.mod h1:HHRXEd7ZlFpthgE+rwAZ6MUVnuJOAeolnaFSthXloUQ= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/api/metadata/annotations.go b/api/metadata/annotations.go deleted file mode 100644 index c85c5f3d..00000000 --- a/api/metadata/annotations.go +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 metadata - -const ( - KubernetesDomain = "app.kubernetes.io" - KubernetesLabelName = KubernetesDomain + "/name" - KubernetesLabelVersion = KubernetesDomain + "/version" - KubernetesLabelInstance = KubernetesDomain + "/instance" - KubernetesLabelPartOf = KubernetesDomain + "/part-of" - KubernetesLabelManagedBy = KubernetesDomain + "/managed-by" - KubernetesLabelComponent = KubernetesDomain + "/component" - Domain = "sonataflow.org" - Key = Domain + "/key" - Name = Domain + "/name" - Description = Domain + "/description" - ExpressionLang = Domain + "/expressionLang" - Version = Domain + "/version" - Label = Domain + "/label" - Profile = Domain + "/profile" - SecondaryPlatformAnnotation = Domain + "/secondary.platform" - OperatorIDAnnotation = Domain + "/operator.id" - RestartedAt = Domain + "/restartedAt" - Checksum = Domain + "/checksum-config" -) - -const ( - // DefaultExpressionLang is the default serverless workflow specification language - DefaultExpressionLang = "jq" - // SpecVersion is the current CNCF Serverless Workflow version supported by the operator - SpecVersion = "0.8" -) - -type QuarkusProfileType string - -func (p QuarkusProfileType) String() string { - return string(p) -} - -const ( - // QuarkusDevProfile the profile used by quarkus in devmode - QuarkusDevProfile QuarkusProfileType = "dev" - // QuarkusProdProfile the profile used by quarkus in an immutable image - QuarkusProdProfile QuarkusProfileType = "prod" -) - -type ProfileType string - -func (p ProfileType) String() string { - return string(p) -} - -const ( - // DevProfile deploys a mutable workflow that can be changed based on .spec.flow definitions CR change. - DevProfile ProfileType = "dev" - // Deprecated: use PreviewProfile. - ProdProfile ProfileType = "prod" - // PreviewProfile is the default profile if none is set. - // The operator will use the platform to do a minimal image build for users to preview an immutable app deployed in the cluster. - // Not suitable for production use cases since the managed build has configuration and resources limitations. - PreviewProfile ProfileType = "preview" - // GitOpsProfile signs the operator that the application image is built externally, skipping any internal managed build. - // Ideally used in production use cases - GitOpsProfile ProfileType = "gitops" -) - -const ( - DefaultProfile = PreviewProfile -) - -// deprecated prod profile is deprecate and not supported, use preview profile -var supportedProfiles = map[ProfileType]ProfileType{DevProfile: DevProfile, PreviewProfile: PreviewProfile, GitOpsProfile: GitOpsProfile} - -func GetProfileOrDefault(annotation map[string]string) ProfileType { - if annotation == nil { - return DefaultProfile - } - if profile, ok := supportedProfiles[ProfileType(annotation[Profile])]; !ok { - return DefaultProfile - } else { - return profile - } -} - -func (p ProfileType) isValidProfile() bool { - _, ok := supportedProfiles[p] - return ok -} - -func IsDevProfile(annotation map[string]string) bool { - if annotation == nil { - return false - } - if len(annotation[Profile]) == 0 { - return false - } - return ProfileType(annotation[Profile]) == DevProfile -} diff --git a/api/metadata/annotations_test.go b/api/metadata/annotations_test.go deleted file mode 100644 index d87cefe8..00000000 --- a/api/metadata/annotations_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 metadata - -import ( - "testing" -) - -func TestGetProfile(t *testing.T) { - type args struct { - annotation map[string]string - } - tests := []struct { - name string - args args - want ProfileType - }{ - {"Empty Annotations", args{annotation: nil}, DefaultProfile}, - {"Non-existent Profile", args{annotation: map[string]string{Profile: "IDontExist"}}, DefaultProfile}, - {"Regular Annotation", args{annotation: map[string]string{Profile: GitOpsProfile.String()}}, GitOpsProfile}, - {"Deprecated Annotation", args{annotation: map[string]string{Profile: ProdProfile.String()}}, DefaultProfile}, - {"Dev Annotation", args{annotation: map[string]string{Profile: DevProfile.String()}}, DevProfile}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := GetProfileOrDefault(tt.args.annotation); got != tt.want { - t.Errorf("GetProfileOrDefault() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestIsValidProfile(t *testing.T) { - profiles := []ProfileType{DefaultProfile, GitOpsProfile, DevProfile} - for _, profile := range profiles { - if !profile.isValidProfile() { - t.Errorf("Profile %s is not valid", profile) - } - } - if ProdProfile.isValidProfile() { - t.Errorf("ProdProfile is deprecated and should not be valid") - } - // any random string should not be a valid profile - if ProfileType("random").isValidProfile() { - t.Errorf("random is not a valid profile") - } -} diff --git a/api/status_types.go b/api/status_types.go index 5ad3ee94..ebbf54e4 100644 --- a/api/status_types.go +++ b/api/status_types.go @@ -205,50 +205,6 @@ func (s *conditionManager) MarkTrueWithReasonf(t ConditionType, reason, messageF }) } -func (s *conditionManager) findUnreadyDependent() *Condition { - // Do not modify the accessors condition order. - conditions := s.reader.GetConditions().DeepCopy() - - // Filter based on terminal status. - n := 0 - for _, c := range conditions { - if c.Type != s.ready { - conditions[n] = c - n++ - } - } - conditions = conditions[:n] - - // Sort set conditions by time. - sort.Slice(conditions, func(i, j int) bool { - return conditions[i].LastUpdateTime.Time.After(conditions[j].LastUpdateTime.Time) - }) - - // First check the conditions with Status == False. - for _, c := range conditions { - // False conditions trump Unknown. - if c.IsFalse() { - return &c - } - } - // Second check for conditions with Status == Unknown. - for _, c := range conditions { - if c.IsUnknown() { - return &c - } - } - - // If something was not initialized. - if len(s.dependents) > len(conditions) { - return &Condition{ - Status: corev1.ConditionUnknown, - } - } - - // All dependents are fine. - return nil -} - // MarkUnknown sets the status of t to Unknown and also sets the ready condition // to Unknown if no other dependent condition is in an error state. func (s *conditionManager) MarkUnknown(t ConditionType, reason, message string) { diff --git a/api/v1/groupversion_info.go b/api/v1/groupversion_info.go new file mode 100644 index 00000000..6ba05e00 --- /dev/null +++ b/api/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 logic v1 API group. +// +kubebuilder:object:generate=true +// +groupName=logic.kubesmarts.org +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "logic.kubesmarts.org", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1/logicflowdefinition_types.go b/api/v1/logicflowdefinition_types.go new file mode 100644 index 00000000..fb05e9ca --- /dev/null +++ b/api/v1/logicflowdefinition_types.go @@ -0,0 +1,64 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// LogicFlowDefinitionSpec defines the desired state of LogicFlowDefinition. +type LogicFlowDefinitionSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of LogicFlowDefinition. Edit logicflowdefinition_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// LogicFlowDefinitionStatus defines the observed state of LogicFlowDefinition. +type LogicFlowDefinitionStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// LogicFlowDefinition is the Schema for the logicflowdefinitions API. +type LogicFlowDefinition struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LogicFlowDefinitionSpec `json:"spec,omitempty"` + Status LogicFlowDefinitionStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// LogicFlowDefinitionList contains a list of LogicFlowDefinition. +type LogicFlowDefinitionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LogicFlowDefinition `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LogicFlowDefinition{}, &LogicFlowDefinitionList{}) +} diff --git a/api/v1/logicflowruntime_types.go b/api/v1/logicflowruntime_types.go new file mode 100644 index 00000000..05267a06 --- /dev/null +++ b/api/v1/logicflowruntime_types.go @@ -0,0 +1,64 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// LogicFlowRuntimeSpec defines the desired state of LogicFlowRuntime. +type LogicFlowRuntimeSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of LogicFlowRuntime. Edit logicflowruntime_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// LogicFlowRuntimeStatus defines the observed state of LogicFlowRuntime. +type LogicFlowRuntimeStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// LogicFlowRuntime is the Schema for the logicflowruntimes API. +type LogicFlowRuntime struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LogicFlowRuntimeSpec `json:"spec,omitempty"` + Status LogicFlowRuntimeStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// LogicFlowRuntimeList contains a list of LogicFlowRuntime. +type LogicFlowRuntimeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LogicFlowRuntime `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LogicFlowRuntime{}, &LogicFlowRuntimeList{}) +} diff --git a/api/v1/logicflowservice_types.go b/api/v1/logicflowservice_types.go new file mode 100644 index 00000000..0fd81311 --- /dev/null +++ b/api/v1/logicflowservice_types.go @@ -0,0 +1,64 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// LogicFlowServiceSpec defines the desired state of LogicFlowService. +type LogicFlowServiceSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of LogicFlowService. Edit logicflowservice_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// LogicFlowServiceStatus defines the observed state of LogicFlowService. +type LogicFlowServiceStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// LogicFlowService is the Schema for the logicflowservices API. +type LogicFlowService struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LogicFlowServiceSpec `json:"spec,omitempty"` + Status LogicFlowServiceStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// LogicFlowServiceList contains a list of LogicFlowService. +type LogicFlowServiceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LogicFlowService `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LogicFlowService{}, &LogicFlowServiceList{}) +} diff --git a/api/v1/logicplatform_types.go b/api/v1/logicplatform_types.go new file mode 100644 index 00000000..97a5d907 --- /dev/null +++ b/api/v1/logicplatform_types.go @@ -0,0 +1,64 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// LogicPlatformSpec defines the desired state of LogicPlatform. +type LogicPlatformSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of LogicPlatform. Edit logicplatform_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// LogicPlatformStatus defines the observed state of LogicPlatform. +type LogicPlatformStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// LogicPlatform is the Schema for the logicplatforms API. +type LogicPlatform struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LogicPlatformSpec `json:"spec,omitempty"` + Status LogicPlatformStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// LogicPlatformList contains a list of LogicPlatform. +type LogicPlatformList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LogicPlatform `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LogicPlatform{}, &LogicPlatformList{}) +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..ba07099f --- /dev/null +++ b/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,381 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 *LogicFlowDefinition) DeepCopyInto(out *LogicFlowDefinition) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowDefinition. +func (in *LogicFlowDefinition) DeepCopy() *LogicFlowDefinition { + if in == nil { + return nil + } + out := new(LogicFlowDefinition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowDefinition) 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 *LogicFlowDefinitionList) DeepCopyInto(out *LogicFlowDefinitionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LogicFlowDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowDefinitionList. +func (in *LogicFlowDefinitionList) DeepCopy() *LogicFlowDefinitionList { + if in == nil { + return nil + } + out := new(LogicFlowDefinitionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowDefinitionList) 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 *LogicFlowDefinitionSpec) DeepCopyInto(out *LogicFlowDefinitionSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowDefinitionSpec. +func (in *LogicFlowDefinitionSpec) DeepCopy() *LogicFlowDefinitionSpec { + if in == nil { + return nil + } + out := new(LogicFlowDefinitionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicFlowDefinitionStatus) DeepCopyInto(out *LogicFlowDefinitionStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowDefinitionStatus. +func (in *LogicFlowDefinitionStatus) DeepCopy() *LogicFlowDefinitionStatus { + if in == nil { + return nil + } + out := new(LogicFlowDefinitionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicFlowRuntime) DeepCopyInto(out *LogicFlowRuntime) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowRuntime. +func (in *LogicFlowRuntime) DeepCopy() *LogicFlowRuntime { + if in == nil { + return nil + } + out := new(LogicFlowRuntime) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowRuntime) 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 *LogicFlowRuntimeList) DeepCopyInto(out *LogicFlowRuntimeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LogicFlowRuntime, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowRuntimeList. +func (in *LogicFlowRuntimeList) DeepCopy() *LogicFlowRuntimeList { + if in == nil { + return nil + } + out := new(LogicFlowRuntimeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowRuntimeList) 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 *LogicFlowRuntimeSpec) DeepCopyInto(out *LogicFlowRuntimeSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowRuntimeSpec. +func (in *LogicFlowRuntimeSpec) DeepCopy() *LogicFlowRuntimeSpec { + if in == nil { + return nil + } + out := new(LogicFlowRuntimeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicFlowRuntimeStatus) DeepCopyInto(out *LogicFlowRuntimeStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowRuntimeStatus. +func (in *LogicFlowRuntimeStatus) DeepCopy() *LogicFlowRuntimeStatus { + if in == nil { + return nil + } + out := new(LogicFlowRuntimeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicFlowService) DeepCopyInto(out *LogicFlowService) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowService. +func (in *LogicFlowService) DeepCopy() *LogicFlowService { + if in == nil { + return nil + } + out := new(LogicFlowService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowService) 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 *LogicFlowServiceList) DeepCopyInto(out *LogicFlowServiceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LogicFlowService, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowServiceList. +func (in *LogicFlowServiceList) DeepCopy() *LogicFlowServiceList { + if in == nil { + return nil + } + out := new(LogicFlowServiceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicFlowServiceList) 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 *LogicFlowServiceSpec) DeepCopyInto(out *LogicFlowServiceSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowServiceSpec. +func (in *LogicFlowServiceSpec) DeepCopy() *LogicFlowServiceSpec { + if in == nil { + return nil + } + out := new(LogicFlowServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicFlowServiceStatus) DeepCopyInto(out *LogicFlowServiceStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicFlowServiceStatus. +func (in *LogicFlowServiceStatus) DeepCopy() *LogicFlowServiceStatus { + if in == nil { + return nil + } + out := new(LogicFlowServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicPlatform) DeepCopyInto(out *LogicPlatform) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicPlatform. +func (in *LogicPlatform) DeepCopy() *LogicPlatform { + if in == nil { + return nil + } + out := new(LogicPlatform) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicPlatform) 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 *LogicPlatformList) DeepCopyInto(out *LogicPlatformList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LogicPlatform, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicPlatformList. +func (in *LogicPlatformList) DeepCopy() *LogicPlatformList { + if in == nil { + return nil + } + out := new(LogicPlatformList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LogicPlatformList) 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 *LogicPlatformSpec) DeepCopyInto(out *LogicPlatformSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicPlatformSpec. +func (in *LogicPlatformSpec) DeepCopy() *LogicPlatformSpec { + if in == nil { + return nil + } + out := new(LogicPlatformSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogicPlatformStatus) DeepCopyInto(out *LogicPlatformStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicPlatformStatus. +func (in *LogicPlatformStatus) DeepCopy() *LogicPlatformStatus { + if in == nil { + return nil + } + out := new(LogicPlatformStatus) + in.DeepCopyInto(out) + return out +} diff --git a/api/v1alpha08/conversion.go b/api/v1alpha08/conversion.go deleted file mode 100644 index 0dcbb84f..00000000 --- a/api/v1alpha08/conversion.go +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - "context" - "errors" - "path" - "regexp" - "strings" - - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - controllerruntime "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/yaml" - - "github.com/kubesmarts/logic-operator/api/metadata" -) - -var namingRegexp = regexp.MustCompile("^[a-z0-9](-?[a-z0-9])*$") -var allowedCharsRegexp = regexp.MustCompile("[^-a-z0-9]") -var startingDashRegexp = regexp.MustCompile("^-+") -var crdVersionRegexp = regexp.MustCompile("v[0-9](alpha|beta)?") - -const ( - // see https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ - dash = "-" - charLimit = 253 -) - -// FromCNCFWorkflow converts the given CNCF Serverless Workflow instance in a new SonataFlow Custom Resource. -func FromCNCFWorkflow(cncfWorkflow *cncfmodel.Workflow, context context.Context) (*SonataFlow, error) { - if cncfWorkflow == nil { - return nil, errors.New("CNCF Workflow is nil") - } - workflowCR := &SonataFlow{ - ObjectMeta: metav1.ObjectMeta{ - Name: extractName(cncfWorkflow), - Annotations: map[string]string{ - metadata.ExpressionLang: string(cncfWorkflow.ExpressionLang), - metadata.Version: cncfWorkflow.Version, - metadata.Description: cncfWorkflow.Description, - }, - }, - } - workflowBytes, err := yaml.Marshal(cncfWorkflow) - if err != nil { - return nil, err - } - workflowCRFlow := &Flow{} - if err = yaml.Unmarshal(workflowBytes, workflowCRFlow); err != nil { - return nil, err - } - workflowCR.Spec.Flow = *workflowCRFlow - - s, _ := SchemeBuilder.Build() - gvks, _, err := s.ObjectKinds(workflowCR) - if err != nil { - return nil, err - } - for _, gvk := range gvks { - if len(gvk.Version) == 0 { - continue - } - workflowCR.SetGroupVersionKind(gvk) - } - warnIfSpecVersionNotSupported(cncfWorkflow, context) - - return workflowCR, nil -} - -// ToCNCFWorkflow converts a SonataFlow object to a Workflow one in order to be able to convert it to a YAML/Json -func ToCNCFWorkflow(workflowCR *SonataFlow, context context.Context) (*cncfmodel.Workflow, error) { - if workflowCR == nil { - return nil, errors.New("SonataFlow is nil") - } - cncfWorkflow := &cncfmodel.Workflow{} - - workflowBytes, err := yaml.Marshal(workflowCR.Spec.Flow) - if err != nil { - return nil, err - } - if err = yaml.Unmarshal(workflowBytes, cncfWorkflow); err != nil { - return nil, err - } - - cncfWorkflow.ID = workflowCR.ObjectMeta.Name - if key, ok := workflowCR.ObjectMeta.Annotations[metadata.Key]; ok { - cncfWorkflow.Key = key - } - if name, ok := workflowCR.ObjectMeta.Annotations[metadata.Name]; ok { - cncfWorkflow.Name = name - } - if description, ok := workflowCR.ObjectMeta.Annotations[metadata.Description]; ok { - cncfWorkflow.Description = description - } - if version, ok := workflowCR.ObjectMeta.Annotations[metadata.Version]; ok { - cncfWorkflow.Version = version - } - cncfWorkflow.SpecVersion = extractSpecVersion(workflowCR) - cncfWorkflow.ExpressionLang = cncfmodel.ExpressionLangType(extractExpressionLang(workflowCR.ObjectMeta.Annotations)) - - warnIfSpecVersionNotSupported(cncfWorkflow, context) - - return cncfWorkflow, nil -} - -// warnIfSpecVersionNotSupported simple check if the version is not supported by the operator. -// Clearly this will be reviewed once we support 0.9. -func warnIfSpecVersionNotSupported(workflow *cncfmodel.Workflow, context context.Context) { - // simple guard to avoid polluting user's log. - if len(workflow.SpecVersion) == 0 { - workflow.SpecVersion = metadata.SpecVersion - return - } - if metadata.SpecVersion != workflow.SpecVersion { - controllerruntime.LoggerFrom(context).Info("SpecVersion not supported", "Workflow SpecVersion", workflow.Version) - } -} - -func extractExpressionLang(annotations map[string]string) string { - expressionLang := annotations[metadata.ExpressionLang] - if expressionLang != "" { - return expressionLang - } - return metadata.DefaultExpressionLang -} - -// Function to extract from the apiVersion the ServerlessWorkflow schema version -// For example given SonataFlow APIVersion, we would like to extract 0.8 -func extractSpecVersion(workflowCR *SonataFlow) string { - schemaVersion := path.Base(workflowCR.APIVersion) - if len(schemaVersion) == 0 { - return metadata.SpecVersion - } - schemaVersion = crdVersionRegexp.ReplaceAllString(schemaVersion, "") - // we only support major minor from the spec - return schemaVersion[0:1] + "." + "" + schemaVersion[1:] -} - -func extractName(workflow *cncfmodel.Workflow) string { - if len(workflow.ID) > 0 { - return sanitizeNaming(workflow.ID) - } - if len(workflow.Key) > 0 { - return sanitizeNaming(workflow.Key) - } - if len(workflow.Name) > 0 { - return sanitizeNaming(workflow.Name) - } - return "" -} - -func sanitizeNaming(name string) string { - if len(name) == 0 || namingRegexp.MatchString(name) { - return name - } - sanitized := startingDashRegexp.ReplaceAllString(allowedCharsRegexp.ReplaceAllString(strings.TrimSpace(strings.ToLower(name)), dash), "") - if len(sanitized) > charLimit { - return sanitized[:charLimit] - } - return sanitized -} diff --git a/api/v1alpha08/conversion_test.go b/api/v1alpha08/conversion_test.go deleted file mode 100644 index 01c295ca..00000000 --- a/api/v1alpha08/conversion_test.go +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - "context" - "os" - "reflect" - "testing" - - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/yaml" -) - -const ( - camelCNCFWorkflow = "testdata/camel.sw.json" - foreachCNCFWorkflow = "testdata/foreach.sw.json" - invalidCNCFWorkflow = "testdata/invalid.sw.json" - camelWorkflowCR = "testdata/sonataflow-camel.yaml" - foreachWorkflowCR = "testdata/sonataflow-foreach.yaml" - invalidWorkflowCR = "testdata/sonataflow-invalid.yaml" -) - -func getCNCFWorkflow(name string) *cncfmodel.Workflow { - workflowBytes, err := os.ReadFile(name) - if err != nil { - panic(err) - } - cncfWorkflow := &cncfmodel.Workflow{} - err = yaml.Unmarshal(workflowBytes, cncfWorkflow) - if err != nil { - panic(err) - } - return cncfWorkflow -} - -func getWorkflowCR(name string) *SonataFlow { - crBytes, err := os.ReadFile(name) - if err != nil { - panic(err) - } - workflowCR := &SonataFlow{} - if err = yaml.Unmarshal(crBytes, workflowCR); err != nil { - panic(err) - } - return workflowCR -} - -func TestFromCNCFWorkflow(t *testing.T) { - type args struct { - cncfWorkflow *cncfmodel.Workflow - } - tests := []struct { - name string - args args - want *SonataFlow - wantErr bool - }{ - {name: "Camel Flow", args: args{getCNCFWorkflow(camelCNCFWorkflow)}, wantErr: false, want: getWorkflowCR(camelWorkflowCR)}, - {name: "ForEach Flow", args: args{getCNCFWorkflow(foreachCNCFWorkflow)}, wantErr: false, want: getWorkflowCR(foreachWorkflowCR)}, - {name: "Invalid Flow", args: args{getCNCFWorkflow(invalidCNCFWorkflow)}, wantErr: false, want: getWorkflowCR(invalidWorkflowCR)}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := FromCNCFWorkflow(tt.args.cncfWorkflow, context.TODO()) - if (err != nil) != tt.wantErr { - t.Errorf("FromCNCFWorkflow() error = %v, wantErr %v", err, tt.wantErr) - return - } - wantUns, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tt.want) - if err != nil { - t.Errorf("%v", err) - } - gotUns, err := runtime.DefaultUnstructuredConverter.ToUnstructured(got) - if err != nil { - t.Errorf("%v", err) - } - if !reflect.DeepEqual(gotUns, wantUns) { - t.Errorf("FromCNCFWorkflow() got = %v, want %v", gotUns, wantUns) - } - }) - } -} - -func TestToCNCFWorkflow(t *testing.T) { - type args struct { - workflowCR *SonataFlow - } - tests := []struct { - name string - args args - want *cncfmodel.Workflow - wantErr bool - }{ - {name: "Camel Flow", args: args{getWorkflowCR(camelWorkflowCR)}, wantErr: false, want: getCNCFWorkflow(camelCNCFWorkflow)}, - {name: "ForEach Flow", args: args{getWorkflowCR(foreachWorkflowCR)}, wantErr: false, want: getCNCFWorkflow(foreachCNCFWorkflow)}, - {name: "Invalid Flow", args: args{getWorkflowCR(invalidWorkflowCR)}, wantErr: false, want: getCNCFWorkflow(invalidCNCFWorkflow)}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ToCNCFWorkflow(tt.args.workflowCR, context.TODO()) - if (err != nil) != tt.wantErr { - t.Errorf("ToCNCFWorkflow() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("ToCNCFWorkflow() got = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_sanitizeNaming(t *testing.T) { - type args struct { - name string - } - tests := []struct { - name string - args args - want string - }{ - {"Success", args{name: "camel-flow"}, "camel-flow"}, - {"Starting Dash", args{name: "-camel-flow"}, "camel-flow"}, - {"All caps", args{name: "CAMEL FLOW"}, "camel-flow"}, - {"Many Dashes", args{name: "--------camel-flow"}, "camel-flow"}, - {"Weird Chars", args{name: "$%#$%$#&#$%#$%#$cm"}, "cm"}, - {"Many Chars", args{name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque posuere nec sapien ac ultricies. Mauris id quam justo. Donec pellentesque facilisis odio eu gravida. Aliquam nisl felis, tincidunt at dignissim id, malesuada eget erat. Duis tempus sapien."}, "lorem-ipsum-dolor-sit-amet--consectetur-adipiscing-elit--quisque-posuere-nec-sapien-ac-ultricies--mauris-id-quam-justo--donec-pellentesque-facilisis-odio-eu-gravida--aliquam-nisl-felis--tincidunt-at-dignissim-id--malesuada-eget-erat--duis-tempus-sapien-"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := sanitizeNaming(tt.args.name); got != tt.want { - t.Errorf("sanitizeNaming() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/api/v1alpha08/groupversion_info.go b/api/v1alpha08/groupversion_info.go deleted file mode 100644 index fc6f85b0..00000000 --- a/api/v1alpha08/groupversion_info.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 contains API Schema definitions for the serverless v1alpha08 API group -// +kubebuilder:object:generate=true -// +groupName=sonataflow.org -package v1alpha08 - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "sonataflow.org", Version: "v1alpha08"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} - - // 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 GroupVersion.WithResource(resource).GroupResource() -} diff --git a/api/v1alpha08/podtemplate_types.go b/api/v1alpha08/podtemplate_types.go deleted file mode 100644 index 574dbedb..00000000 --- a/api/v1alpha08/podtemplate_types.go +++ /dev/null @@ -1,574 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -// ContainerSpec is the container for the internal deployments based on the default Kubernetes Container API -type ContainerSpec struct { - // Container image name. - // More info: https://kubernetes.io/docs/concepts/containers/images - // This field is optional to allow higher level config management to default or override - // container images in workload controllers like Deployments and StatefulSets. - // +optional - Image string `json:"image,omitempty" protobuf:"bytes,2,opt,name=image"` - // Entrypoint array. Not executed within a shell. - // The container image's ENTRYPOINT is used if this is not provided. - // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - // of whether the variable exists or not. Cannot be updated. - // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - // +optional - Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"` - // Arguments to the entrypoint. - // The container image's CMD is used if this is not provided. - // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - // of whether the variable exists or not. Cannot be updated. - // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - // +optional - Args []string `json:"args,omitempty" protobuf:"bytes,4,rep,name=args"` - // List of ports to expose from the container. Not specifying a port here - // DOES NOT prevent that port from being exposed. Any port which is - // listening on the default "0.0.0.0" address inside a container will be - // accessible from the network. - // Modifying this array with strategic merge patch may corrupt the data. - // For more information See https://github.com/kubernetes/kubernetes/issues/108255. - // Cannot be updated. - // +optional - // +patchMergeKey=containerPort - // +patchStrategy=merge - // +listType=map - // +listMapKey=containerPort - // +listMapKey=protocol - Ports []corev1.ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"` - // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple - // sources, the value associated with the last source will take precedence. - // Values defined by an Env with a duplicate key will take precedence. - // Cannot be updated. - // +optional - EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty" protobuf:"bytes,19,rep,name=envFrom"` - // List of environment variables to set in the container. - // Cannot be updated. - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - Env []corev1.EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,7,rep,name=env"` - // Compute Resources required by this container. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - // +optional - Resources corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,8,opt,name=resources"` - // Resources resize policy for the container. - // +featureGate=InPlacePodVerticalScaling - // +optional - // +listType=atomic - ResizePolicy []corev1.ContainerResizePolicy `json:"resizePolicy,omitempty" protobuf:"bytes,23,rep,name=resizePolicy"` - // Pod volumes to mount into the container's filesystem. - // Cannot be updated. - // +optional - // +patchMergeKey=mountPath - // +patchStrategy=merge - VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"` - // volumeDevices is the list of block devices to be used by the container. - // +patchMergeKey=devicePath - // +patchStrategy=merge - // +optional - VolumeDevices []corev1.VolumeDevice `json:"volumeDevices,omitempty" patchStrategy:"merge" patchMergeKey:"devicePath" protobuf:"bytes,21,rep,name=volumeDevices"` - // Periodic probe of container liveness. - // Container will be restarted if the probe fails. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,10,opt,name=livenessProbe"` - // Periodic probe of container service readiness. - // Container will be removed from service endpoints if the probe fails. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // StartupProbe indicates that the Pod has successfully initialized. - // If specified, no other probes are executed until this completes successfully. - // If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - // This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - // when it might take a long time to load data or warm a cache, than during steady-state operation. - // This cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - StartupProbe *corev1.Probe `json:"startupProbe,omitempty" protobuf:"bytes,22,opt,name=startupProbe"` - // Actions that the management system should take in response to container lifecycle events. - // Cannot be updated. - // +optional - Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty" protobuf:"bytes,12,opt,name=lifecycle"` - // Optional: Path at which the file to which the container's termination message - // will be written is mounted into the container's filesystem. - // Message written is intended to be brief final status, such as an assertion failure message. - // Will be truncated by the node if greater than 4096 bytes. The total message length across - // all containers will be limited to 12kb. - // Defaults to /dev/termination-log. - // Cannot be updated. - // +optional - TerminationMessagePath string `json:"terminationMessagePath,omitempty" protobuf:"bytes,13,opt,name=terminationMessagePath"` - // Indicate how the termination message should be populated. File will use the contents of - // terminationMessagePath to populate the container status message on both success and failure. - // FallbackToLogsOnError will use the last chunk of container log output if the termination - // message file is empty and the container exited with an error. - // The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - // Defaults to File. - // Cannot be updated. - // +optional - TerminationMessagePolicy corev1.TerminationMessagePolicy `json:"terminationMessagePolicy,omitempty" protobuf:"bytes,20,opt,name=terminationMessagePolicy,casttype=TerminationMessagePolicy"` - // Image pull policy. - // One of Always, Never, IfNotPresent. - // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - // +optional - ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty" protobuf:"bytes,14,opt,name=imagePullPolicy,casttype=PullPolicy"` - // SecurityContext defines the security options the container should be run with. - // If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - // +optional - SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty" protobuf:"bytes,15,opt,name=securityContext"` - - // Variables for interactive containers, these have very specialized use-cases (e.g. debugging) - // and shouldn't be used for general purpose containers. - - // Whether this container should allocate a buffer for stdin in the container runtime. If this - // is not set, reads from stdin in the container will always result in EOF. - // Default is false. - // +optional - Stdin bool `json:"stdin,omitempty" protobuf:"varint,16,opt,name=stdin"` - // Whether the container runtime should close the stdin channel after it has been opened by - // a single attach. When stdin is true the stdin stream will remain open across multiple attach - // sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - // first client attaches to stdin, and then remains open and accepts data until the client disconnects, - // at which time stdin is closed and remains closed until the container is restarted. If this - // flag is false, a container processes that reads from stdin will never receive an EOF. - // Default is false - // +optional - StdinOnce bool `json:"stdinOnce,omitempty" protobuf:"varint,17,opt,name=stdinOnce"` - // Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - // Default is false. - // +optional - TTY bool `json:"tty,omitempty" protobuf:"varint,18,opt,name=tty"` -} - -// ToContainer converts to Kubernetes Container API. -func (f *ContainerSpec) ToContainer() corev1.Container { - return corev1.Container{ - Name: DefaultContainerName, - Image: f.Image, - Command: f.Command, - Args: f.Args, - Ports: f.Ports, - EnvFrom: f.EnvFrom, - Env: f.Env, - Resources: f.Resources, - ResizePolicy: f.ResizePolicy, - VolumeMounts: f.VolumeMounts, - VolumeDevices: f.VolumeDevices, - LivenessProbe: f.LivenessProbe, - ReadinessProbe: f.ReadinessProbe, - StartupProbe: f.StartupProbe, - Lifecycle: f.Lifecycle, - TerminationMessagePath: f.TerminationMessagePath, - TerminationMessagePolicy: f.TerminationMessagePolicy, - ImagePullPolicy: f.ImagePullPolicy, - SecurityContext: f.SecurityContext, - Stdin: f.Stdin, - StdinOnce: f.StdinOnce, - TTY: f.TTY, - } -} - -// PodSpec describes the PodSpec for the internal deployments based on the default Kubernetes PodSpec API -type PodSpec struct { - // List of volumes that can be mounted by containers belonging to the pod. - // More info: https://kubernetes.io/docs/concepts/storage/volumes - // +optional - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - Volumes []corev1.Volume `json:"volumes,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,1,rep,name=volumes"` - // List of initialization containers belonging to the pod. - // Init containers are executed in order prior to containers being started. If any - // init container fails, the pod is considered to have failed and is handled according - // to its restartPolicy. The name for an init container or normal container must be - // unique among all containers. - // Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - // The resourceRequirements of an init container are taken into account during scheduling - // by finding the highest request/limit for each resource type, and then using the max of - // of that value or the sum of the normal containers. Limits are applied to init containers - // in a similar fashion. - // Init containers cannot currently be added or removed. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - // +patchMergeKey=name - // +patchStrategy=merge - InitContainers []corev1.Container `json:"initContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,20,rep,name=initContainers"` - // List of containers belonging to the pod. - // Containers cannot currently be added or removed. - // There must be at least one container in a Pod. - // Cannot be updated. - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - Containers []corev1.Container `json:"containers,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=containers"` - // Restart policy for all containers within the pod. - // One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - // Default to Always. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - // +optional - RestartPolicy corev1.RestartPolicy `json:"restartPolicy,omitempty" protobuf:"bytes,3,opt,name=restartPolicy,casttype=RestartPolicy"` - // Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - // Value must be non-negative integer. The value zero indicates stop immediately via - // the kill signal (no opportunity to shut down). - // If this value is nil, the default grace period will be used instead. - // The grace period is the duration in seconds after the processes running in the pod are sent - // a termination signal and the time when the processes are forcibly halted with a kill signal. - // Set this value longer than the expected cleanup time for your process. - // Defaults to 30 seconds. - // +optional - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - // Optional duration in seconds the pod may be active on the node relative to - // StartTime before the system will actively try to mark it failed and kill associated containers. - // Value must be a positive integer. - // +optional - ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty" protobuf:"varint,5,opt,name=activeDeadlineSeconds"` - // Set DNS policy for the pod. - // Defaults to "ClusterFirst". - // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - // To have DNS options set along with hostNetwork, you have to specify DNS policy - // explicitly to 'ClusterFirstWithHostNet'. - // +optional - DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty" protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"` - // 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 - // +mapType=atomic - NodeSelector map[string]string `json:"nodeSelector,omitempty" protobuf:"bytes,7,rep,name=nodeSelector"` - - // ServiceAccountName is the name of the ServiceAccount to use to run this pod. - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - // +optional - ServiceAccountName string `json:"serviceAccountName,omitempty" protobuf:"bytes,8,opt,name=serviceAccountName"` - // AutomountServiceAccountToken indicates whether a service account token should be automatically mounted. - // +optional - AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty" protobuf:"varint,21,opt,name=automountServiceAccountToken"` - - // NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - // the scheduler simply schedules this pod onto that node, assuming that it fits resource - // requirements. - // +optional - NodeName string `json:"nodeName,omitempty" protobuf:"bytes,10,opt,name=nodeName"` - // Host networking requested for this pod. Use the host's network namespace. - // If this option is set, the ports that will be used must be specified. - // Default to false. - // +k8s:conversion-gen=false - // +optional - HostNetwork bool `json:"hostNetwork,omitempty" protobuf:"varint,11,opt,name=hostNetwork"` - // Use the host's pid namespace. - // Optional: Default to false. - // +k8s:conversion-gen=false - // +optional - HostPID bool `json:"hostPID,omitempty" protobuf:"varint,12,opt,name=hostPID"` - // Use the host's ipc namespace. - // Optional: Default to false. - // +k8s:conversion-gen=false - // +optional - HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"` - // Share a single process namespace between all of the containers in a pod. - // When this is set containers will be able to view and signal processes from other containers - // in the same pod, and the first process in each container will not be assigned PID 1. - // HostPID and ShareProcessNamespace cannot both be set. - // Optional: Default to false. - // +k8s:conversion-gen=false - // +optional - ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty" protobuf:"varint,27,opt,name=shareProcessNamespace"` - // SecurityContext holds pod-level security attributes and common container settings. - // Optional: Defaults to empty. See type description for default values of each field. - // +optional - SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty" protobuf:"bytes,14,opt,name=securityContext"` - // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - // If specified, these secrets will be passed to individual puller implementations for them to use. - // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,15,rep,name=imagePullSecrets"` - // Specifies the hostname of the Pod - // If not specified, the pod's hostname will be set to a system-defined value. - // +optional - Hostname string `json:"hostname,omitempty" protobuf:"bytes,16,opt,name=hostname"` - // If specified, the fully qualified Pod hostname will be "...svc.". - // If not specified, the pod will not have a domainname at all. - // +optional - Subdomain string `json:"subdomain,omitempty" protobuf:"bytes,17,opt,name=subdomain"` - // If specified, the pod's scheduling constraints - // +optional - Affinity *corev1.Affinity `json:"affinity,omitempty" protobuf:"bytes,18,opt,name=affinity"` - // If specified, the pod will be dispatched by specified scheduler. - // If not specified, the pod will be dispatched by default scheduler. - // +optional - SchedulerName string `json:"schedulerName,omitempty" protobuf:"bytes,19,opt,name=schedulerName"` - // If specified, the pod's tolerations. - // +optional - Tolerations []corev1.Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"` - // HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - // file if specified. This is only valid for non-hostNetwork pods. - // +optional - // +patchMergeKey=ip - // +patchStrategy=merge - HostAliases []corev1.HostAlias `json:"hostAliases,omitempty" patchStrategy:"merge" patchMergeKey:"ip" protobuf:"bytes,23,rep,name=hostAliases"` - // If specified, indicates the pod's priority. "system-node-critical" and - // "system-cluster-critical" are two special keywords which indicate the - // highest priorities with the former being the highest priority. Any other - // name must be defined by creating a PriorityClass object with that name. - // If not specified, the pod priority will be default or zero if there is no - // default. - // +optional - PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,24,opt,name=priorityClassName"` - // The priority value. Various system components use this field to find the - // priority of the pod. When Priority Admission Controller is enabled, it - // prevents users from setting this field. The admission controller populates - // this field from PriorityClassName. - // The higher the value, the higher the priority. - // +optional - Priority *int32 `json:"priority,omitempty" protobuf:"bytes,25,opt,name=priority"` - // Specifies the DNS parameters of a pod. - // Parameters specified here will be merged to the generated DNS - // configuration based on DNSPolicy. - // +optional - DNSConfig *corev1.PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` - // If specified, all readiness gates will be evaluated for pod readiness. - // A pod is ready when all its containers are ready AND - // all conditions specified in the readiness gates have status equal to "True" - // More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - // +optional - ReadinessGates []corev1.PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"` - // RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - // to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - // If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - // empty definition that uses the default runtime handler. - // More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - // +optional - RuntimeClassName *string `json:"runtimeClassName,omitempty" protobuf:"bytes,29,opt,name=runtimeClassName"` - // EnableServiceLinks indicates whether information about services should be injected into pod's - // environment variables, matching the syntax of Docker links. - // Optional: Defaults to true. - // +optional - EnableServiceLinks *bool `json:"enableServiceLinks,omitempty" protobuf:"varint,30,opt,name=enableServiceLinks"` - // PreemptionPolicy is the Policy for preempting pods with lower priority. - // One of Never, PreemptLowerPriority. - // Defaults to PreemptLowerPriority if unset. - // +optional - PreemptionPolicy *corev1.PreemptionPolicy `json:"preemptionPolicy,omitempty" protobuf:"bytes,31,opt,name=preemptionPolicy"` - // Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - // This field will be autopopulated at admission time by the RuntimeClass admission controller. If - // the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - // The RuntimeClass admission controller will reject Pod create requests which have the overhead already - // set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - // defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - // More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - // +optional - Overhead corev1.ResourceList `json:"overhead,omitempty" protobuf:"bytes,32,opt,name=overhead"` - // TopologySpreadConstraints describes how a group of pods ought to spread across topology - // domains. Scheduler will schedule pods in a way which abides by the constraints. - // All topologySpreadConstraints are ANDed. - // +optional - // +patchMergeKey=topologyKey - // +patchStrategy=merge - // +listType=map - // +listMapKey=topologyKey - // +listMapKey=whenUnsatisfiable - TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty" patchStrategy:"merge" patchMergeKey:"topologyKey" protobuf:"bytes,33,opt,name=topologySpreadConstraints"` - // If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - // In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - // In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - // If a pod does not have FQDN, this has no effect. - // Default to false. - // +optional - SetHostnameAsFQDN *bool `json:"setHostnameAsFQDN,omitempty" protobuf:"varint,35,opt,name=setHostnameAsFQDN"` - // Specifies the OS of the containers in the pod. - // Some pod and container fields are restricted if this is set. - // - // If the OS field is set to linux, the following fields must be unset: - // -securityContext.windowsOptions - // - // If the OS field is set to windows, following fields must be unset: - // - spec.hostPID - // - spec.hostIPC - // - spec.hostUsers - // - spec.securityContext.seLinuxOptions - // - spec.securityContext.seccompProfile - // - spec.securityContext.fsGroup - // - spec.securityContext.fsGroupChangePolicy - // - spec.securityContext.sysctls - // - spec.shareProcessNamespace - // - spec.securityContext.runAsUser - // - spec.securityContext.runAsGroup - // - spec.securityContext.supplementalGroups - // - spec.containers[*].securityContext.seLinuxOptions - // - spec.containers[*].securityContext.seccompProfile - // - spec.containers[*].securityContext.capabilities - // - spec.containers[*].securityContext.readOnlyRootFilesystem - // - spec.containers[*].securityContext.privileged - // - spec.containers[*].securityContext.allowPrivilegeEscalation - // - spec.containers[*].securityContext.procMount - // - spec.containers[*].securityContext.runAsUser - // - spec.containers[*].securityContext.runAsGroup - // +optional - OS *corev1.PodOS `json:"os,omitempty" protobuf:"bytes,36,opt,name=os"` - - // Use the host's user namespace. - // Optional: Default to true. - // If set to true or not present, the pod will be run in the host user namespace, useful - // for when the pod needs a feature only available to the host user namespace, such as - // loading a kernel module with CAP_SYS_MODULE. - // When set to false, a new userns is created for the pod. Setting false is useful for - // mitigating container breakout vulnerabilities even allowing users to run their - // containers as root without actually having root privileges on the host. - // This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - // +k8s:conversion-gen=false - // +optional - HostUsers *bool `json:"hostUsers,omitempty" protobuf:"bytes,37,opt,name=hostUsers"` - - // SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - // If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - // scheduler will not attempt to schedule the pod. - // - // SchedulingGates can only be set at pod creation time, and be removed only afterwards. - // - // This is a beta feature enabled by the PodSchedulingReadiness feature gate. - // - // +patchMergeKey=name - // +patchStrategy=merge - // +listType=map - // +listMapKey=name - // +featureGate=PodSchedulingReadiness - // +optional - SchedulingGates []corev1.PodSchedulingGate `json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,38,opt,name=schedulingGates"` - // ResourceClaims defines which ResourceClaims must be allocated - // and reserved before the Pod is allowed to start. The resources - // will be made available to those containers which consume them - // by name. - // - // This is an alpha field and requires enabling the - // DynamicResourceAllocation feature gate. - // - // This field is immutable. - // - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +featureGate=DynamicResourceAllocation - // +optional - ResourceClaims []corev1.PodResourceClaim `json:"resourceClaims,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,39,rep,name=resourceClaims"` -} - -func (f *PodSpec) ToPodSpec() corev1.PodSpec { - return corev1.PodSpec{ - Volumes: f.Volumes, - InitContainers: f.InitContainers, - Containers: f.Containers, - RestartPolicy: f.RestartPolicy, - TerminationGracePeriodSeconds: f.TerminationGracePeriodSeconds, - ActiveDeadlineSeconds: f.ActiveDeadlineSeconds, - DNSPolicy: f.DNSPolicy, - NodeSelector: f.NodeSelector, - ServiceAccountName: f.ServiceAccountName, - AutomountServiceAccountToken: f.AutomountServiceAccountToken, - NodeName: f.NodeName, - HostNetwork: f.HostNetwork, - HostPID: f.HostPID, - HostIPC: f.HostIPC, - ShareProcessNamespace: f.ShareProcessNamespace, - SecurityContext: f.SecurityContext, - ImagePullSecrets: f.ImagePullSecrets, - Hostname: f.Hostname, - Subdomain: f.Subdomain, - Affinity: f.Affinity, - SchedulerName: f.SchedulerName, - Tolerations: f.Tolerations, - HostAliases: f.HostAliases, - PriorityClassName: f.PriorityClassName, - Priority: f.Priority, - DNSConfig: f.DNSConfig, - ReadinessGates: f.ReadinessGates, - RuntimeClassName: f.RuntimeClassName, - EnableServiceLinks: f.EnableServiceLinks, - PreemptionPolicy: f.PreemptionPolicy, - Overhead: f.Overhead, - TopologySpreadConstraints: f.TopologySpreadConstraints, - SetHostnameAsFQDN: f.SetHostnameAsFQDN, - OS: f.OS, - HostUsers: f.HostUsers, - SchedulingGates: f.SchedulingGates, - ResourceClaims: f.ResourceClaims, - } -} - -// PodDisruptionBudgetSpec describes the Kubernetes pod disruption budget configuration for the SonataFlow and supporting -// services pods. -type PodDisruptionBudgetSpec struct { - // An eviction is allowed if at least "minAvailable" pods selected by - // "selector" will still be available after the eviction, i.e. even in the - // absence of the evicted pod. So for example you can prevent all voluntary - // evictions by specifying "100%". This is a mutually exclusive setting with "maxUnavailable". - // +optional - MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty" protobuf:"bytes,1,opt,name=minAvailable"` - - // An eviction is allowed if at most "maxUnavailable" pods selected by - // "selector" are unavailable after the eviction, i.e. even in absence of - // the evicted pod. For example, one can prevent all voluntary evictions - // by specifying 0. This is a mutually exclusive setting with "minAvailable". - // +optional - MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,3,opt,name=maxUnavailable"` -} - -// PodTemplateSpec describes the desired custom Kubernetes PodTemplate definition for a service. -// -// The ContainerSpec describes the container where the service is running. It will override any default definitions. -// For example, to override the image one can use `.spec.podTemplate.container.image = my/image:tag`. -type PodTemplateSpec struct { - // Container is the Kubernetes container where the application should run. - // One can change this attribute in order to override the defaults provided by the operator. - // +optional - Container ContainerSpec `json:"container,omitempty"` - // +optional - PodSpec `json:",inline"` - // +optional - Replicas *int32 `json:"replicas,omitempty"` - // Defines the Kubernetes PodDisruptionBudgetSpec for this service. When configured, the SonataFlowPlatform controller - // will automatically create a PodDisruptionBudget based on this specification that targets the service Deployment. - // Currently only apply for the Data Index. - // +optional - PodDisruptionBudget *PodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"` -} diff --git a/api/v1alpha08/sonataflow_persistence_types.go b/api/v1alpha08/sonataflow_persistence_types.go deleted file mode 100644 index abac8df2..00000000 --- a/api/v1alpha08/sonataflow_persistence_types.go +++ /dev/null @@ -1,121 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 v1alpha08 - -type DBMigrationStrategyType string - -const ( - DBMigrationStrategyService DBMigrationStrategyType = "service" - DBMigrationStrategyJob DBMigrationStrategyType = "job" - DBMigrationStrategyNone DBMigrationStrategyType = "none" -) - -// PlatformPersistenceOptionsSpec configures the DataBase in the platform spec. This specification can -// be used by workflows and platform services when they don't provide one of their own. -// +optional -// +kubebuilder:validation:MaxProperties=1 -type PlatformPersistenceOptionsSpec struct { - // Connect configured services to a postgresql database. - // +optional - PostgreSQL *PlatformPersistencePostgreSQL `json:"postgresql,omitempty"` -} - -// PlatformPersistencePostgreSQL configure postgresql connection in a platform to be shared -// by platform services and workflows when required. -// +kubebuilder:validation:MinProperties=2 -// +kubebuilder:validation:MaxProperties=2 -type PlatformPersistencePostgreSQL struct { - // Secret reference to the database user credentials - SecretRef PostgreSQLSecretOptions `json:"secretRef"` - // Service reference to postgresql datasource. Mutually exclusive to jdbcUrl. - // +optional - ServiceRef *SQLServiceOptions `json:"serviceRef,omitempty"` - // PostgreSql JDBC URL. Mutually exclusive to serviceRef. - // e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - // +optional - JdbcUrl string `json:"jdbcUrl,omitempty"` -} - -// PersistenceOptionsSpec configures the DataBase support for both platform services and workflows. For services, it allows -// configuring a generic database connectivity if the service does not come with its own configured. In case of workflows, -// the operator will add the necessary JDBC properties to in the workflow's application.properties so that it can communicate -// with the persistence service based on the spec provided here. -// +optional -// +kubebuilder:validation:MaxProperties=2 -type PersistenceOptionsSpec struct { - // Connect configured services to a postgresql database. - // +optional - PostgreSQL *PersistencePostgreSQL `json:"postgresql,omitempty"` - - // DB Migration approach for data-index and jobs-service. Use the following values as described. - // job: use job based approach provided by the SonataFlow operator. - // service: service itself shall migrate the db and will not use SonataFlow operator. - // none: no database migration functionality needed. - // +optional - // +kubebuilder:default:=service - DBMigrationStrategy string `json:"dbMigrationStrategy,omitempty"` -} - -// PersistencePostgreSQL configure postgresql connection for service(s). -// +kubebuilder:validation:MinProperties=2 -// +kubebuilder:validation:MaxProperties=2 -type PersistencePostgreSQL struct { - // Secret reference to the database user credentials - SecretRef PostgreSQLSecretOptions `json:"secretRef"` - // Service reference to postgresql datasource. Mutually exclusive to jdbcUrl. - // +optional - ServiceRef *PostgreSQLServiceOptions `json:"serviceRef,omitempty"` - // PostgreSql JDBC URL. Mutually exclusive to serviceRef. - // e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - // +optional - JdbcUrl string `json:"jdbcUrl,omitempty"` -} - -// PostgreSQLSecretOptions use credential secret for postgresql connection. -type PostgreSQLSecretOptions struct { - // Name of the postgresql credentials secret. - Name string `json:"name"` - // Defaults to POSTGRESQL_USER - // +optional - UserKey string `json:"userKey,omitempty"` - // Defaults to POSTGRESQL_PASSWORD - // +optional - PasswordKey string `json:"passwordKey,omitempty"` -} - -type SQLServiceOptions struct { - // Name of the postgresql k8s service. - Name string `json:"name"` - // Namespace of the postgresql k8s service. Defaults to the SonataFlowPlatform's local namespace. - // +optional - Namespace string `json:"namespace,omitempty"` - // Port to use when connecting to the postgresql k8s service. Defaults to 5432. - // +optional - Port *int `json:"port,omitempty"` - // Name of postgresql database to be used. Defaults to "sonataflow" - // +optional - DatabaseName string `json:"databaseName,omitempty"` -} - -// PostgreSQLServiceOptions use k8s service to configure postgresql jdbc url. -type PostgreSQLServiceOptions struct { - *SQLServiceOptions `json:",inline"` - // Schema of postgresql database to be used. Defaults to "data-index-service" - // +optional - DatabaseSchema string `json:"databaseSchema,omitempty"` -} diff --git a/api/v1alpha08/sonataflow_types.go b/api/v1alpha08/sonataflow_types.go deleted file mode 100644 index 7fed93d7..00000000 --- a/api/v1alpha08/sonataflow_types.go +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" - - "github.com/kubesmarts/logic-operator/api" -) - -const DefaultContainerName = "workflow" - -// DeploymentModel defines how a given pod will be deployed -// +kubebuilder:validation:Enum=kubernetes;knative -type DeploymentModel string - -const ( - // KubernetesDeploymentModel defines a PodSpec to be deployed as a regular Kubernetes Deployment - KubernetesDeploymentModel DeploymentModel = "kubernetes" - // KnativeDeploymentModel defines a PodSpec to be deployed as a Knative Serving Service - KnativeDeploymentModel DeploymentModel = "knative" -) - -// FlowPodTemplateSpec is a special PodTemplateSpec designed for SonataFlow deployments -type FlowPodTemplateSpec struct { - // Container is the Kubernetes container where the application should run. - // One can change this attribute in order to override the defaults provided by the operator. - // +optional - Container ContainerSpec `json:"container,omitempty"` - // +optional - PodSpec `json:",inline"` - // +optional - // Replicas define the number of pods to start by default for this deployment model. Ignored in "knative" deployment model. - Replicas *int32 `json:"replicas,omitempty"` - // Defines the kind of deployment model for this pod spec. In dev profile, only "kubernetes" is valid. - // +optional - DeploymentModel DeploymentModel `json:"deploymentModel,omitempty"` - // Defines the Kubernetes PodDisruptionBudgetSpec for this workflow. When configured, the SonataFlow controller will - // automatically create a PodDisruptionBudget based on this specification that targets the workflow Deployment. - // Ignored in "knative" deployment model, and dev profile workflows. - // +optional - PodDisruptionBudget *PodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"` -} - -// Flow describes the contents of the Workflow definition following the CNCF Serverless Workflow Specification. -// The attributes not part of the flow are defined by the Custom Resource metadata information, as follows: -// -// - Id, name, and key are replaced by the Custom Resource's name. Must follow the Kubernetes naming patterns (RFC1123). -// -// - Description can be added in the CR's annotation field sonataflow.org/description -// -// - Version is also defined in the CR's annotation, field sonataflow.org/version -// -// - SpecVersion is in the CR's apiVersion, for example v1alpha08 means that it follows the specification version 0.8. -type Flow struct { - // Workflow start definition. - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - // +optional - Start *cncfmodel.Start `json:"start,omitempty"` - // Annotations List of helpful terms describing the workflows intended purpose, subject areas, or other important - // qualities. - // +optional - Annotations []string `json:"annotations,omitempty"` - // DataInputSchema URI of the JSON Schema used to validate the workflow data input - // +optional - DataInputSchema *cncfmodel.DataInputSchema `json:"dataInputSchema,omitempty"` - // Secrets allow you to access sensitive information, such as passwords, OAuth tokens, ssh keys, etc, - // inside your Workflow Expressions. - // +optional - Secrets cncfmodel.Secrets `json:"secrets,omitempty"` - // Constants Workflow constants are used to define static, and immutable, data which is available to - // Workflow Expressions. - // +optional - Constants *cncfmodel.Constants `json:"constants,omitempty"` - // Defines the workflow default timeout settings. - // +optional - Timeouts *cncfmodel.Timeouts `json:"timeouts,omitempty"` - // Defines checked errors that can be explicitly handled during workflow execution. - // +optional - Errors cncfmodel.Errors `json:"errors,omitempty"` - // If "true", workflow instances is not terminated when there are no active execution paths. - // Instance can be terminated with "terminate end definition" or reaching defined "workflowExecTimeout" - // +optional - KeepActive bool `json:"keepActive,omitempty"` - // Metadata custom information shared with the runtime. - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - // +optional - Metadata cncfmodel.Metadata `json:"metadata,omitempty"` - // AutoRetries If set to true, actions should automatically be retried on unchecked errors. Default is false - // +optional - AutoRetries bool `json:"autoRetries,omitempty"` - // Auth definitions can be used to define authentication information that should be applied to resources defined - // in the operation property of function definitions. It is not used as authentication information for the - // function invocation, but just to access the resource containing the function invocation information. - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - // +optional - Auth cncfmodel.Auths `json:"auth,omitempty" validate:"omitempty"` - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:pruning:PreserveUnknownFields - States []cncfmodel.State `json:"states" validate:"required,min=1,dive"` - // +optional - Events cncfmodel.Events `json:"events,omitempty"` - // +optional - Functions cncfmodel.Functions `json:"functions,omitempty"` - // +optional - Retries cncfmodel.Retries `json:"retries,omitempty" validate:"dive"` -} - -// WorkflowResources collection of local objects holding workflow resources, such as OpenAPI files -// that will be mounted in the workflow application. -type WorkflowResources struct { - ConfigMaps []ConfigMapWorkflowResource `json:"configMaps,omitempty"` -} - -// ConfigMapWorkflowResource ConfigMap local reference holding one or more workflow resources, such as OpenAPI files -// that will be mounted in the workflow application. -type ConfigMapWorkflowResource struct { - // ConfigMap the given configMap name in the same workflow context to find the resource - // +kubebuilder:validation:Required - ConfigMap corev1.LocalObjectReference `json:"configMap"` - // WorkflowPath path relative to the workflow application root file system within the pod (//src/main/resources). - // Starting trailing slashes will be removed. - WorkflowPath string `json:"workflowPath,omitempty"` -} - -// SonataFlowSpec defines the desired state of SonataFlow -// +k8s:openapi-gen=true -type SonataFlowSpec struct { - // Flow the workflow definition. - // +kubebuilder:validation:Required - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="flow" - Flow Flow `json:"flow"` - // Resources workflow resources that are linked to this workflow definition. - // For example, a collection of OpenAPI specification files. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="resources" - Resources WorkflowResources `json:"resources,omitempty"` - // PodTemplate describes the deployment details of this SonataFlow instance. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate" - PodTemplate FlowPodTemplateSpec `json:"podTemplate,omitempty"` - // Persistence defines the database persistence configuration for the workflow - Persistence *PersistenceOptionsSpec `json:"persistence,omitempty"` - // Sink describes the sinkBinding details of this SonataFlow instance. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="sink" - Sink *duckv1.Destination `json:"sink,omitempty"` - // Sources describes the list of sources used to create triggers for events consumed by this SonataFlow instance. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="sources" - Sources []SonataFlowSourceSpec `json:"sources,omitempty"` -} - -// SonataFlowSourceSpec defines the desired state of a source used for trigger creation -// +k8s:openapi-gen=true -type SonataFlowSourceSpec struct { - // Defines the eventType to filter the events - EventType string `json:"eventType"` - // Defines the broker used - duckv1.Destination `json:",inline"` -} - -// SonataFlowStatus defines the observed state of SonataFlow -// +k8s:openapi-gen=true -type SonataFlowStatus struct { - api.Status `json:",inline"` - // Address is used as a part of Addressable interface (status.address.url) for knative - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="address" - Address duckv1.Addressable `json:"address,omitempty"` - // keeps track of how many failure recovers a given workflow had so far - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="recoverFailureAttempts" - RecoverFailureAttempts int `json:"recoverFailureAttempts,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="lastTimeRecoverAttempt" - LastTimeRecoverAttempt metav1.Time `json:"lastTimeRecoverAttempt,omitempty"` - // Endpoint is an externally accessible URL of the workflow - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="endpoint" - Endpoint *apis.URL `json:"endpoint,omitempty"` - // Services displays which platform services are being used by this workflow - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="services" - Services *PlatformServicesStatus `json:"services,omitempty"` - // Platform displays which platform is being used by this workflow - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="platform" - Platform *SonataFlowPlatformRef `json:"platform,omitempty"` - // Triggers list of triggers created for the SonataFlow - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="triggers" - Triggers []SonataFlowTriggerRef `json:"triggers,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="flowRevision" - FlowCRC int32 `json:"flowCRC,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="finalizerAttempts" - FinalizerAttempts int `json:"finalizerAttempts,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="finalizerSucceed" - FinalizerSucceed bool `json:"finalizerSucceed,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="lastTimeFinalizerAttempt" - LastTimeFinalizerAttempt *metav1.Time `json:"lastTimeFinalizerAttempt,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="lastTimeStatusNotified" - LastTimeStatusNotified *metav1.Time `json:"lastTimeStatusNotified,omitempty"` - // Replicas is the actual number of observed queryable pods. - // This is required by the HPA via the scale subresource. - // +optional - Replicas int32 `json:"replicas,omitempty"` - // Selector is the queryable label selector for pods, in string format. - // HPA uses this to find the pods and collect metrics (CPU/Memory). - // +optional - Selector string `json:"selector,omitempty"` -} - -// SonataFlowTriggerRef defines a trigger created for the SonataFlow. -type SonataFlowTriggerRef struct { - // Name of the Trigger - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trigger_Name" - Name string `json:"name"` - // Namespace of the Trigger - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trigger_NS" - Namespace string `json:"namespace"` -} - -func (s *SonataFlowStatus) GetTopLevelConditionType() api.ConditionType { - return api.RunningConditionType -} - -func (s *SonataFlowStatus) IsReady() bool { - return s.GetTopLevelCondition().IsTrue() -} - -func (s *SonataFlowStatus) GetTopLevelCondition() *api.Condition { - return s.GetCondition(s.GetTopLevelConditionType()) -} - -func (s *SonataFlowStatus) Manager() api.ConditionsManager { - return api.NewConditionManager(s, api.RunningConditionType, api.BuiltConditionType) -} - -func (s *SonataFlowStatus) IsWaitingForPlatform() bool { - cond := s.GetCondition(api.BuiltConditionType) - return cond.IsFalse() && cond.Reason == api.WaitingForPlatformReason -} - -func (s *SonataFlowStatus) IsWaitingForDeployment() bool { - cond := s.GetCondition(api.RunningConditionType) - return cond.IsFalse() && cond.Reason == api.WaitingForDeploymentReason -} - -// IsChildObjectsProblem indicates a problem during objects creation during reconciliation -// For example, a deployment that couldn't be created or a referenced object not found. -func (s *SonataFlowStatus) IsChildObjectsProblem() bool { - cond := s.GetCondition(api.RunningConditionType) - // You can add more conditions that meet this conditional here - return cond.IsFalse() && (cond.Reason == api.ExternalResourcesNotFoundReason) -} - -func (s *SonataFlowStatus) IsWaitingForBuild() bool { - cond := s.GetCondition(api.RunningConditionType) - return cond.IsFalse() && cond.Reason == api.WaitingForBuildReason -} - -func (s *SonataFlowStatus) IsBuildRunningOrUnknown() bool { - cond := s.GetCondition(api.BuiltConditionType) - return cond.IsUnknown() || (cond.IsFalse() && cond.Reason == api.BuildIsRunningReason) -} - -func (s *SonataFlowStatus) IsBuildRunning() bool { - cond := s.GetCondition(api.BuiltConditionType) - return cond.IsFalse() && cond.Reason == api.BuildIsRunningReason -} - -func (s *SonataFlowStatus) IsBuildFailed() bool { - cond := s.GetCondition(api.BuiltConditionType) - return cond.IsFalse() && cond.Reason == api.BuildFailedReason -} - -// SetReplicas sets the number of ready replicas for the /scale subresource contract. -func (s *SonataFlowStatus) SetReplicas(replicas int32) { - s.Replicas = replicas -} - -// SetSelector sets the target pods selector for the /scale subresource contract. -func (s *SonataFlowStatus) SetSelector(selector string) { - s.Selector = selector -} - -// SonataFlow is the descriptor representation for a workflow application based on the CNCF Serverless Workflow specification. -// +kubebuilder:object:root=true -// +kubebuilder:object:generate=true -// +kubebuilder:subresource:status -// +kubebuilder:subresource:scale:specpath=.spec.podTemplate.replicas,statuspath=.status.replicas,selectorpath=.status.selector -// +kubebuilder:resource:shortName={"sf", "workflow", "workflows"} -// +k8s:openapi-gen=true -// +kubebuilder:printcolumn:name="Profile",type=string,JSONPath=`.metadata.annotations.sonataflow\.org\/profile` -// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.metadata.annotations.sonataflow\.org\/version` -// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.status.endpoint` -// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=='Running')].status` -// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=='Running')].reason` -// +operator-sdk:csv:customresourcedefinitions:resources={{SonataFlowBuild,sonataflow.org/v1alpha08,"A SonataFlow Build"}} -// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,apps/v1,"A Deployment for the Flow"}} -// +operator-sdk:csv:customresourcedefinitions:resources={{Service,serving.knative.dev/v1,"A Knative Serving Service for the Flow"}} -// +operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,"A Service for the Flow"}} -// +operator-sdk:csv:customresourcedefinitions:resources={{Route,route.openshift.io/v1,"An OpenShift Route for the Flow"}} -// +operator-sdk:csv:customresourcedefinitions:resources={{ConfigMap,v1,"The ConfigMaps with Flow definition and additional configuration files"}} -// +operator-sdk:csv:customresourcedefinitions:displayName="SonataFlow" -type SonataFlow struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SonataFlowSpec `json:"spec,omitempty"` - Status SonataFlowStatus `json:"status,omitempty"` -} - -func (s *SonataFlow) IsKnativeDeployment() bool { - return s.Spec.PodTemplate.DeploymentModel == KnativeDeploymentModel -} - -func (s *SonataFlow) HasContainerSpecImage() bool { - return len(s.Spec.PodTemplate.Container.Image) > 0 -} - -// SonataFlowList contains a list of SonataFlow -// +kubebuilder:object:root=true -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type SonataFlowList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []SonataFlow `json:"items"` -} - -func init() { - SchemeBuilder.Register(&SonataFlow{}, &SonataFlowList{}) -} diff --git a/api/v1alpha08/sonataflowbuild_types.go b/api/v1alpha08/sonataflowbuild_types.go deleted file mode 100644 index 29967829..00000000 --- a/api/v1alpha08/sonataflowbuild_types.go +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - "encoding/json" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - - "github.com/kubesmarts/logic-operator/api/metadata" -) - -type BuildPhase string - -const ( - // BuildPhaseNone -- - BuildPhaseNone BuildPhase = "" - // BuildPhaseInitialization -- - BuildPhaseInitialization BuildPhase = "Initialization" - // BuildPhaseScheduling -- - BuildPhaseScheduling BuildPhase = "Scheduling" - // BuildPhasePending -- - BuildPhasePending BuildPhase = "Pending" - // BuildPhaseRunning -- - BuildPhaseRunning BuildPhase = "Running" - // BuildPhaseSucceeded -- - BuildPhaseSucceeded BuildPhase = "Succeeded" - // BuildPhaseFailed -- - BuildPhaseFailed BuildPhase = "Failed" - // BuildPhaseInterrupted -- - BuildPhaseInterrupted BuildPhase = "Interrupted" - // BuildPhaseError -- - BuildPhaseError BuildPhase = "Error" -) - -// BuildRestartAnnotation marks a SonataFlowBuild to restart -const BuildRestartAnnotation = metadata.Domain + "/restartBuild" - -// BuildTemplate an abstraction over the actual build process performed by the platform. -// +k8s:openapi-gen=true -type BuildTemplate struct { - // Timeout defines the Build maximum execution duration. - // The Build deadline is set to the Build start time plus the Timeout duration. - // If the Build deadline is exceeded, the Build context is canceled, - // and its phase set to BuildPhaseFailed. - // +kubebuilder:validation:Format=duration - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Timeout" - Timeout metav1.Duration `json:"timeout,omitempty"` - // Resources optional compute resource requirements for the builder - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resources" - Resources corev1.ResourceRequirements `json:"resources,omitempty"` - // Arguments lists the command line arguments to send to the internal builder command. - // Depending on the build method you might set this attribute instead of BuildArgs. - // For example: ".spec.arguments=verbose=3". - // Please see the SonataFlow guides. - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Arguments" - Arguments []string `json:"arguments,omitempty"` - // Optional build arguments that can be set to the internal build (e.g. Docker ARG) - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="BuildArgs" - BuildArgs []corev1.EnvVar `json:"buildArgs,omitempty"` - // Optional environment variables to add to the internal build - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Envs" - Envs []corev1.EnvVar `json:"envs,omitempty"` -} - -// SonataFlowBuildSpec define the desired state of th SonataFlowBuild. -// +k8s:openapi-gen=true -type SonataFlowBuildSpec struct { - BuildTemplate `json:",inline"` -} - -// SonataFlowBuildStatus defines the observed state of SonataFlowBuild -// +k8s:openapi-gen=true -type SonataFlowBuildStatus struct { - // ImageTag The final image tag produced by this build instance - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="ImageTag" - ImageTag string `json:"imageTag,omitempty"` - // BuildPhase Current phase of the build - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="BuildPhase" - BuildPhase BuildPhase `json:"buildPhase,omitempty"` - // Error Last error found during build - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="Error" - Error string `json:"error,omitempty"` - // InnerBuild is a reference to an internal build object, which can be anything known only to internal builders. - // +kubebuilder:pruning:PreserveUnknownFields - // +optional - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="InnerBuild" - InnerBuild runtime.RawExtension `json:"innerBuild,omitempty" patchStrategy:"replace"` -} - -// SetInnerBuild use to define a new object pointer to the inner build. -func (k *SonataFlowBuildStatus) SetInnerBuild(innerBuilder interface{}) error { - obj, err := json.Marshal(innerBuilder) - if err != nil { - return err - } - k.InnerBuild.Raw = obj - return nil -} - -// GetInnerBuild fetch into the given inner build the value from unstructured. -func (k *SonataFlowBuildStatus) GetInnerBuild(innerBuild interface{}) error { - if len(k.InnerBuild.Raw) == 0 { - return nil - } - if err := json.Unmarshal(k.InnerBuild.Raw, innerBuild); err != nil { - return err - } - return nil -} - -// SonataFlowBuild is an internal custom resource to control workflow build instances in the target platform -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:object:root=true -// +kubebuilder:object:generate=true -// +kubebuilder:subresource:status -// +k8s:openapi-gen=true -// +kubebuilder:printcolumn:name="Image",type=string,JSONPath=`.status.imageTag` -// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.buildPhase` -// +kubebuilder:resource:shortName={"sfb", "sfbuild", "sfbuilds"} -// +operator-sdk:csv:customresourcedefinitions:resources={{BuildConfig,build.openshift.io/v1,"An Openshift Build Config"}} -// +operator-sdk:csv:customresourcedefinitions:displayName="SonataFlowBuild" -type SonataFlowBuild struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SonataFlowBuildSpec `json:"spec,omitempty"` - Status SonataFlowBuildStatus `json:"status,omitempty"` -} - -// SonataFlowBuildList is the Schema for the sonataflowbuildsList API -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:object:root=true -// +kubebuilder:object:generate=true -type SonataFlowBuildList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []SonataFlowBuild `json:"items"` -} - -func init() { - SchemeBuilder.Register(&SonataFlowBuild{}, &SonataFlowBuildList{}) -} diff --git a/api/v1alpha08/sonataflowclusterplatform_types.go b/api/v1alpha08/sonataflowclusterplatform_types.go deleted file mode 100644 index 3ba27e19..00000000 --- a/api/v1alpha08/sonataflowclusterplatform_types.go +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api" -) - -const ( - // SonataFlowClusterPlatformKind is the Kind name of the SonataFlowClusterPlatform CR - SonataFlowClusterPlatformKind string = "SonataFlowClusterPlatform" - PlatformNotFoundReason string = "PlatformNotFound" -) - -// SonataFlowClusterPlatformSpec defines the desired state of SonataFlowClusterPlatform -type SonataFlowClusterPlatformSpec struct { - // PlatformRef defines which existing SonataFlowPlatform's supporting services should be used cluster-wide. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="PlatformRef" - PlatformRef SonataFlowPlatformRef `json:"platformRef"` - // Capabilities defines which platform capabilities should be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]` - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Capabilities" - Capabilities *SonataFlowClusterPlatformCapSpec `json:"capabilities,omitempty"` -} - -// SonataFlowClusterPlatformCapSpec defines which platform capabilities should be applied cluster-wide -type SonataFlowClusterPlatformCapSpec struct { - // Workflows defines which platform capabilities should be applied to workflows cluster-wide. - Workflows []WorkFlowCapability `json:"workflows,omitempty"` -} - -// +kubebuilder:validation:Enum=services -type WorkFlowCapability string - -// SonataFlowPlatformRef defines which existing SonataFlowPlatform's supporting services should be used cluster-wide. -type SonataFlowPlatformRef struct { - // Name of the SonataFlowPlatform - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Platform_Name" - Name string `json:"name"` - // Namespace of the SonataFlowPlatform - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Platform_NS" - Namespace string `json:"namespace"` -} - -// SonataFlowClusterPlatformStatus defines the observed state of SonataFlowClusterPlatform -type SonataFlowClusterPlatformStatus struct { - api.Status `json:",inline"` - // Version the operator version controlling this ClusterPlatform - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="version" - Version string `json:"version,omitempty"` -} - -func (in *SonataFlowClusterPlatformStatus) GetTopLevelConditionType() api.ConditionType { - return api.SucceedConditionType -} - -func (in *SonataFlowClusterPlatformStatus) IsReady() bool { - return in.GetTopLevelCondition().IsTrue() -} - -func (in *SonataFlowClusterPlatformStatus) GetTopLevelCondition() *api.Condition { - return in.GetCondition(in.GetTopLevelConditionType()) -} - -func (in *SonataFlowClusterPlatformStatus) Manager() api.ConditionsManager { - return api.NewConditionManager(in, api.SucceedConditionType) -} - -func (in *SonataFlowClusterPlatformStatus) IsDuplicated() bool { - cond := in.GetTopLevelCondition() - return cond.IsFalse() && cond.Reason == PlatformDuplicatedReason -} - -// SonataFlowClusterPlatform is the Schema for the sonataflowclusterplatforms API -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:scope=Cluster -// +kubebuilder:printcolumn:name="Platform_Name",type=string,JSONPath=`.spec.platformRef.name` -// +kubebuilder:printcolumn:name="Platform_NS",type=string,JSONPath=`.spec.platformRef.namespace` -// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=='Succeed')].status` -// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=='Succeed')].reason` -// +operator-sdk:csv:customresourcedefinitions:resources={{SonataFlowPlatform,sonataflow.org/v1alpha08,"A SonataFlow Platform"}} -// +operator-sdk:csv:customresourcedefinitions:displayName="SonataFlowClusterPlatform" -type SonataFlowClusterPlatform struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SonataFlowClusterPlatformSpec `json:"spec,omitempty"` - Status SonataFlowClusterPlatformStatus `json:"status,omitempty"` -} - -//+kubebuilder:object:root=true - -// SonataFlowClusterPlatformList contains a list of SonataFlowClusterPlatform -type SonataFlowClusterPlatformList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []SonataFlowClusterPlatform `json:"items"` -} - -func init() { - SchemeBuilder.Register(&SonataFlowClusterPlatform{}, &SonataFlowClusterPlatformList{}) -} diff --git a/api/v1alpha08/sonataflowclusterplatform_types_support.go b/api/v1alpha08/sonataflowclusterplatform_types_support.go deleted file mode 100644 index 8c126555..00000000 --- a/api/v1alpha08/sonataflowclusterplatform_types_support.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NewSonataFlowClusterPlatformList returns an empty list of ClusterPlatform objects -func NewSonataFlowClusterPlatformList() SonataFlowClusterPlatformList { - return SonataFlowClusterPlatformList{ - TypeMeta: metav1.TypeMeta{ - APIVersion: GroupVersion.String(), - Kind: SonataFlowClusterPlatformKind, - }, - } -} diff --git a/api/v1alpha08/sonataflowplatform_build_types.go b/api/v1alpha08/sonataflowplatform_build_types.go deleted file mode 100644 index 289c96cf..00000000 --- a/api/v1alpha08/sonataflowplatform_build_types.go +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - "strconv" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// Describes the general build specification for this platform. Specific for build scenarios. -type BuildPlatformSpec struct { - // Describes a build template for building workflows. Base for the internal SonataFlowBuild resource. - Template BuildTemplate `json:"template,omitempty"` - // Describes the platform configuration for building workflows. - Config BuildPlatformConfig `json:"config,omitempty"` -} - -// Describes the configuration for building in the given platform -type BuildPlatformConfig struct { - // a base image that can be used as base layer for all images. - // It can be useful if you want to provide some custom base image with further utility software - BaseImage string `json:"baseImage,omitempty"` - // how much time to wait before time out the build process - Timeout *metav1.Duration `json:"timeout,omitempty"` - // BuildStrategy to use to build workflows in the platform. - // Usually, the operator elect the strategy based on the platform. - // Note that this field might be read only in certain scenarios. - BuildStrategy BuildStrategy `json:"strategy,omitempty"` - // BuildStrategyOptions additional options to add to the build strategy. - // See https://sonataflow.org/serverlessworkflow/main/cloud/operator/build-and-deploy-workflows.html - BuildStrategyOptions map[string]string `json:"strategyOptions,omitempty"` - // Registry the registry where to publish the built image - Registry RegistrySpec `json:"registry,omitempty"` -} - -// GetTimeout returns the specified duration or a default one -func (b *BuildPlatformConfig) GetTimeout() metav1.Duration { - if b.Timeout == nil { - return metav1.Duration{} - } - return *b.Timeout -} - -// IsStrategyOptionEnabled return whether the BuildStrategyOptions is enabled or not -func (b *BuildPlatformConfig) IsStrategyOptionEnabled(option string) bool { - if enabled, ok := b.BuildStrategyOptions[option]; ok { - res, err := strconv.ParseBool(enabled) - if err != nil { - return false - } - return res - } - return false -} - -func (b *BuildPlatformConfig) IsStrategyOptionEmpty(option string) bool { - if v, ok := b.BuildStrategyOptions[option]; ok { - return len(v) == 0 - } - return false -} - -// RegistrySpec provides the configuration for the container registry -type RegistrySpec struct { - // if the container registry is insecure (ie, http only) - Insecure bool `json:"insecure,omitempty"` - // the URI to access - Address string `json:"address,omitempty"` - // the secret where credentials are stored - Secret string `json:"secret,omitempty"` - // the configmap which stores the Certificate Authority - CA string `json:"ca,omitempty"` - // the registry organization - Organization string `json:"organization,omitempty"` -} - -type BuildStrategy string - -const ( - // OperatorBuildStrategy uses the operator builder to perform the workflow build - // E.g. on Minikube or Kubernetes the container-builder strategies - OperatorBuildStrategy BuildStrategy = "operator" - // PlatformBuildStrategy uses the cluster to perform the build. - // E.g. on OpenShift, BuildConfig. - PlatformBuildStrategy BuildStrategy = "platform" - - // In the future we can have "custom" which will delegate the build to an external actor provided by the administrator - // See https://issues.redhat.com/browse/KOGITO-9084 -) diff --git a/api/v1alpha08/sonataflowplatform_devmode_types.go b/api/v1alpha08/sonataflowplatform_devmode_types.go deleted file mode 100644 index ef5ced33..00000000 --- a/api/v1alpha08/sonataflowplatform_devmode_types.go +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -// DevModePlatformSpec describes the devmode configuration for the given platform. -type DevModePlatformSpec struct { - // Base image to run the Workflow in dev mode instead of the operator's default. - BaseImage string `json:"baseImage,omitempty"` -} diff --git a/api/v1alpha08/sonataflowplatform_property_types.go b/api/v1alpha08/sonataflowplatform_property_types.go deleted file mode 100644 index 11f0636f..00000000 --- a/api/v1alpha08/sonataflowplatform_property_types.go +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import v1 "k8s.io/api/core/v1" - -// PropertyPlatformSpec defines the struct for global managed properties in the SonataFlowPlatform. -// These properties are ignored in the SonataFlowClusterPlatform since a source of a property (PropertyVarSource) can only be local. -type PropertyPlatformSpec struct { - // Properties that will be added to the SonataFlow managed configMaps in the current context. - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - Flow []PropertyVar `json:"flow,omitempty" patchStrategy:"merge" patchMergeKey:"name"` -} - -// PropertyVar is the entry for a property set derived from the Kubernetes API EnvVar. -// Note that the name doesn't have to match C_IDENTIFIER. -type PropertyVar struct { - // The property name - Name string `json:"name"` - - // Optional: no more than one of the following may be specified. - - // Defaults to "". - // +optional - Value string `json:"value,omitempty"` - // Source for the property's value. Cannot be used if value is not empty. - // +optional - ValueFrom *PropertyVarSource `json:"valueFrom,omitempty"` -} - -// PropertyVarSource is the definition of a property source derived from the Kubernetes API EnvVarSource. -type PropertyVarSource struct { - // Selects a key of a ConfigMap. - // +optional - ConfigMapKeyRef *v1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"` - // Selects a key of a secret in the flow's namespace - // +optional - SecretKeyRef *v1.SecretKeySelector `json:"secretKeyRef,omitempty"` -} diff --git a/api/v1alpha08/sonataflowplatform_services_types.go b/api/v1alpha08/sonataflowplatform_services_types.go deleted file mode 100644 index a098d3a8..00000000 --- a/api/v1alpha08/sonataflowplatform_services_types.go +++ /dev/null @@ -1,69 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - duckv1 "knative.dev/pkg/apis/duck/v1" -) - -// ServicesPlatformSpec describes the desired service configuration for workflows without the `sonataflow.org/profile: dev` annotation. -type ServicesPlatformSpec struct { - // Deploys the Data Index service for use by workflows without the `sonataflow.org/profile: dev` annotation. - // +optional - DataIndex *DataIndexServiceSpec `json:"dataIndex,omitempty"` - // Deploys the Job service for use by workflows without the `sonataflow.org/profile: dev` annotation. - // +optional - JobService *JobServiceServiceSpec `json:"jobService,omitempty"` -} - -// DataIndexServiceSpec defines the desired state of Dataindex service -// +k8s:openapi-gen=true -type DataIndexServiceSpec struct { - // Defines the common spec of a platform service - ServiceSpec `json:",inline"` - // Defines the source where the Dataindex receives events from - // +optional - Source *duckv1.Destination `json:"source,omitempty"` -} - -// JobServiceServiceSpec defines the desired state of Jobservice service -// +k8s:openapi-gen=true -type JobServiceServiceSpec struct { - // Defines the common spec of a platform service - ServiceSpec `json:",inline"` - // Defines the sink where the Jobservice sends events to - // +optional - Sink *duckv1.Destination `json:"sink,omitempty"` - // Defines the source where the Jobservice receives events from - // +optional - Source *duckv1.Destination `json:"source,omitempty"` -} - -// ServiceSpec defines the desired state of a platform service -// +k8s:openapi-gen=true -type ServiceSpec struct { - // Determines whether workflows without the `sonataflow.org/profile: dev` annotation should be configured to use this service - // +optional - Enabled *bool `json:"enabled,omitempty"` - // Persists service to a datasource of choice. Ephemeral by default. - // +optional - Persistence *PersistenceOptionsSpec `json:"persistence,omitempty"` - // PodTemplate describes the deployment details of this platform service instance. - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate" - PodTemplate PodTemplateSpec `json:"podTemplate,omitempty"` -} diff --git a/api/v1alpha08/sonataflowplatform_types.go b/api/v1alpha08/sonataflowplatform_types.go deleted file mode 100644 index ce26a99f..00000000 --- a/api/v1alpha08/sonataflowplatform_types.go +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - duckv1 "knative.dev/pkg/apis/duck/v1" - - "github.com/kubesmarts/logic-operator/api" -) - -const ( - // SonataFlowPlatformKind is the Kind name of the SonataFlowPlatform CR - SonataFlowPlatformKind string = "SonataFlowPlatform" -) - -// SonataFlowPlatformSpec defines the desired state of SonataFlowPlatform -// +k8s:openapi-gen=true -type SonataFlowPlatformSpec struct { - // Build Attributes for building workflows in the target platform - // +optional - // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Build" - Build BuildPlatformSpec `json:"build,omitempty"` - // DevMode Attributes for running workflows in devmode (immutable, no build required) - // +optional - // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="DevMode" - DevMode DevModePlatformSpec `json:"devMode,omitempty"` - // Services attributes for deploying supporting applications like Data Index & Job Service. - // Only workflows without the `sonataflow.org/profile: dev` annotation will be configured to use these service(s). - // Setting this will override the use of any cluster-scoped services that might be defined via `SonataFlowClusterPlatform`. - // +optional - // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Services" - Services *ServicesPlatformSpec `json:"services,omitempty"` - // Eventing describes the information required for Knative Eventing integration in the platform. - // +optional - Eventing *PlatformEventingSpec `json:"eventing,omitempty"` - // Persistence defines the platform persistence configuration. When this field is set, - // the configuration is used as the persistence for platform services and SonataFlow instances - // that don't provide one of their own. - // +optional - Persistence *PlatformPersistenceOptionsSpec `json:"persistence,omitempty"` - // Properties defines the property set for a given actor in the current context. - // For example, the workflow managed properties. One can define here a set of properties for SonataFlow deployments - // that will be reused across every workflow deployment. - // - // These properties MAY NOT be propagated to a SonataFlowClusterPlatform since PropertyVarSource can only refer local context sources. - // +optional - Properties *PropertyPlatformSpec `json:"properties,omitempty"` - // Settings for Prometheus monitoring - // +optional - Monitoring *PlatformMonitoringOptionsSpec `json:"monitoring,omitempty"` -} - -// PlatformEventingSpec specifies the Knative Eventing integration details in the platform. -// +k8s:openapi-gen=true -type PlatformEventingSpec struct { - // Broker to communicate with workflow deployment. It can be the default broker when the workflow, Dataindex, or Jobservice does not have a sink or source specified. - // +optional - // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="broker" - Broker *duckv1.Destination `json:"broker,omitempty"` -} - -// PlatformMonitoringOptionsSpec specifies the settings for monitoring -// +k8s:openapi-gen=true -type PlatformMonitoringOptionsSpec struct { - // Enabled indicates whether monitoring with Prometheus metrics is enabled - // +optional - // +default: false - Enabled bool `json:"enabled,omitempty"` -} - -// PlatformCluster is the kind of orchestration cluster the platform is installed into -// +kubebuilder:validation:Enum=kubernetes;openshift -type PlatformCluster string - -const ( - // PlatformClusterOpenShift is used when targeting an OpenShift cluster - PlatformClusterOpenShift PlatformCluster = "openshift" - // PlatformClusterKubernetes is used when targeting a Kubernetes cluster - PlatformClusterKubernetes PlatformCluster = "kubernetes" -) - -const ( - PlatformCreatingReason = "Creating" - PlatformWarmingReason = "Warming" - PlatformFailureReason = "Failure" - PlatformDuplicatedReason = "Duplicated" -) - -type DBMigrationStatus string - -const ( - DBMigrationStatusStarted DBMigrationStatus = "Started" - DBMigrationStatusInProgress DBMigrationStatus = "In-Progress" - DBMigrationStatusSucceeded DBMigrationStatus = "Succeeded" - DBMigrationStatusFailed DBMigrationStatus = "Failed" - - MessageDBMigrationStatusStarted string = "Started the database migrations for the services" - MessageDBMigrationStatusInProgress string = "The database migrations for the services are in-progress" - MessageDBMigrationStatusSucceeded string = "The database migrations for the services are successful" - MessageDBMigrationStatusFailed string = "The database migrations for the services have failed" - - ReasonDBMigrationStatusStarted string = "Started by SonataFlow operator" - ReasonDBMigrationStatusInProgress string = "The database migration job is in-progress" - ReasonDBMigrationStatusSucceeded string = "The database migration job completed as expected" - ReasonDBMigrationStatusFailed string = "The database may be unreachable, invalid credentials supplied or flyway migration failed. Please check logs for further details." -) - -type SonataFlowPlatformDBMigrationPhase struct { - Status DBMigrationStatus `json:"dbMigrationStatus,omitempty"` - Message string `json:"message,omitempty"` - Reason string `json:"reason,omitempty"` -} - -// SonataFlowPlatformStatus defines the observed state of SonataFlowPlatform -// +k8s:openapi-gen=true -type SonataFlowPlatformStatus struct { - api.Status `json:",inline"` - // Cluster what kind of cluster you're running (ie, plain Kubernetes or OpenShift) - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="cluster" - Cluster PlatformCluster `json:"cluster,omitempty"` - // Version the operator version controlling this Platform - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="version" - Version string `json:"version,omitempty"` - // Info generic information related to the Platform - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="info" - Info map[string]string `json:"info,omitempty"` - // ClusterPlatformRef information related to the (optional) active SonataFlowClusterPlatform - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="clusterPlatformRef" - ClusterPlatformRef *SonataFlowClusterPlatformRefStatus `json:"clusterPlatformRef,omitempty"` - // Triggers list of triggers created for the SonataFlowPlatform - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="triggers" - Triggers []SonataFlowPlatformTriggerRef `json:"triggers,omitempty"` - //+operator-sdk:csv:customresourcedefinitions:type=status,displayName="dbMigrationStatus" - SonataFlowPlatformDBMigrationPhase *SonataFlowPlatformDBMigrationPhase `json:"sonataFlowPlatformDBMigrationPhase,omitempty"` -} - -// SonataFlowPlatformTriggerRef defines a trigger created for the SonataFlowPlatform. -type SonataFlowPlatformTriggerRef struct { - // Name of the Trigger - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trigger_Name" - Name string `json:"name"` - // Namespace of the Trigger - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trigger_NS" - Namespace string `json:"namespace"` -} - -// SonataFlowClusterPlatformRefStatus information related to the (optional) active SonataFlowClusterPlatform -// +k8s:openapi-gen=true -type SonataFlowClusterPlatformRefStatus struct { - // Name of the active SonataFlowClusterPlatform - Name string `json:"name,omitempty"` - // PlatformRef displays which SonataFlowPlatform has been referenced by the active SonataFlowClusterPlatform - PlatformRef SonataFlowPlatformRef `json:"platformRef,omitempty"` - // Services displays which cluster-wide services are being used by this SonataFlowPlatform - Services *PlatformServicesStatus `json:"services,omitempty"` -} - -// PlatformServicesStatus displays which cluster-wide services are being used by a SonataFlowPlatform or SonataFlow -// +k8s:openapi-gen=true -type PlatformServicesStatus struct { - // DataIndexRef displays information on the cluster-wide Data Index service - DataIndexRef *PlatformServiceRefStatus `json:"dataIndexRef,omitempty"` - // JobServiceRef displays information on the cluster-wide Job Service - JobServiceRef *PlatformServiceRefStatus `json:"jobServiceRef,omitempty"` -} - -// PlatformServiceRefStatus displays information on a cluster-wide service -// +k8s:openapi-gen=true -type PlatformServiceRefStatus struct { - // Url displays the base url of the service - Url string `json:"url,omitempty"` -} - -func (in *SonataFlowPlatformStatus) GetTopLevelConditionType() api.ConditionType { - return api.SucceedConditionType -} - -func (in *SonataFlowPlatformStatus) IsReady() bool { - return in.GetTopLevelCondition().IsTrue() -} - -func (in *SonataFlowPlatformStatus) GetTopLevelCondition() *api.Condition { - return in.GetCondition(in.GetTopLevelConditionType()) -} - -func (in *SonataFlowPlatformStatus) Manager() api.ConditionsManager { - return api.NewConditionManager(in, api.SucceedConditionType) -} - -func (in *SonataFlowPlatformStatus) IsCreating() bool { - cond := in.GetTopLevelCondition() - return cond.IsFalse() && cond.Reason == PlatformCreatingReason -} - -func (in *SonataFlowPlatformStatus) IsWarming() bool { - cond := in.GetTopLevelCondition() - return cond.IsFalse() && cond.Reason == PlatformWarmingReason -} - -func (in *SonataFlowPlatformStatus) IsDuplicated() bool { - cond := in.GetTopLevelCondition() - return cond.IsFalse() && cond.Reason == PlatformDuplicatedReason -} - -func (in *SonataFlowPlatformStatus) IsFailure() bool { - cond := in.GetTopLevelCondition() - return cond.IsFalse() && cond.Reason == PlatformFailureReason -} - -// SonataFlowPlatform is the descriptor for the workflow platform infrastructure. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:object:root=true -// +kubebuilder:object:generate=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:shortName={"sfp", "sfplatform", "sfplatforms"} -// +kubebuilder:printcolumn:name="Cluster",type=string,JSONPath=`.status.cluster` -// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=='Succeed')].status` -// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=='Succeed')].reason` -// +operator-sdk:csv:customresourcedefinitions:resources={{Namespace,v1,"The Namespace controlled by the platform"}} -// +operator-sdk:csv:customresourcedefinitions:displayName="SonataFlowPlatform" -type SonataFlowPlatform struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SonataFlowPlatformSpec `json:"spec,omitempty"` - Status SonataFlowPlatformStatus `json:"status,omitempty"` -} - -// SonataFlowPlatformList contains a list of SonataFlowPlatform -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:object:root=true -// +kubebuilder:object:generate=true -type SonataFlowPlatformList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []SonataFlowPlatform `json:"items"` -} - -func init() { - SchemeBuilder.Register(&SonataFlowPlatform{}, &SonataFlowPlatformList{}) -} diff --git a/api/v1alpha08/sonataflowplatform_types_support.go b/api/v1alpha08/sonataflowplatform_types_support.go deleted file mode 100644 index 5c058e7b..00000000 --- a/api/v1alpha08/sonataflowplatform_types_support.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 v1alpha08 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NewSonataFlowPlatformList returns an empty list of Platform objects -func NewSonataFlowPlatformList() SonataFlowPlatformList { - return SonataFlowPlatformList{ - TypeMeta: metav1.TypeMeta{ - APIVersion: GroupVersion.String(), - Kind: SonataFlowPlatformKind, - }, - } -} diff --git a/api/v1alpha08/testdata/camel.sw.json b/api/v1alpha08/testdata/camel.sw.json deleted file mode 100644 index b54ecda6..00000000 --- a/api/v1alpha08/testdata/camel.sw.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "id": "camel-custom-function", - "version": "1.0.0", - "start": "start", - "specVersion": "0.8", - "functions": [ - { - "name": "callSoap", - "type": "custom", - "operation": "camel:direct:numberToWords" - } - ], - "dataInputSchema": "camel.sw.schema.json", - "states": [ - { - "name": "start", - "type": "operation", - "actions": [ - { - "functionRef": { - "refName": "callSoap", - "arguments": { - "body": "${ .number }" - } - } - } - ], - "stateDataFilter": { - "output": "${ words = .response[0]}" - }, - "end": true - } - ] -} diff --git a/api/v1alpha08/testdata/foreach.sw.json b/api/v1alpha08/testdata/foreach.sw.json deleted file mode 100644 index 2d4b6933..00000000 --- a/api/v1alpha08/testdata/foreach.sw.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "foreach", - "version": "1.0", - "description": "An example of how to use for each state", - "start": "start", - "specVersion": "0.8", - "functions": [ - { - "name": "printMessage", - "type": "custom", - "operation": "sysout" - }, - { - "name": "increase", - "type": "expression", - "operation": ".item + 1" - } - ], - "states": [ - { - "name": "start", - "type": "foreach", - "iterationParam": "item", - "inputCollection": ".input", - "outputCollection": ".output", - "stateDataFilter": { - "output": "{output: .output}" - }, - "actions": [ - { - "name": "increase", - "functionRef": { - "refName": "increase" - } - }, - { - "name": "printAction", - "functionRef": { - "refName": "printMessage", - "arguments": { - "message": ".item" - } - } - } - ], - "end": true - } - ] -} diff --git a/api/v1alpha08/testdata/invalid.sw.json b/api/v1alpha08/testdata/invalid.sw.json deleted file mode 100644 index d72e2d4f..00000000 --- a/api/v1alpha08/testdata/invalid.sw.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "id": "invalid", - "version": "1.0", - "specVersion": "0.8", - "description": "A valid workflow should have states." -} diff --git a/api/v1alpha08/testdata/sonataflow-camel.yaml b/api/v1alpha08/testdata/sonataflow-camel.yaml deleted file mode 100644 index 588fe97a..00000000 --- a/api/v1alpha08/testdata/sonataflow-camel.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: camel-custom-function - annotations: - sonataflow.org/version: 1.0.0 - sonataflow.org/expressionLang: jq - sonataflow.org/description: "" -spec: - flow: - start: start - functions: - - name: callSoap - type: custom - operation: camel:direct:numberToWords - dataInputSchema: camel.sw.schema.json - states: - - name: start - type: operation - actions: - - functionRef: - refName: callSoap - arguments: - body: "${ .number }" - stateDataFilter: - output: "${ words = .response[0]}" - end: true diff --git a/api/v1alpha08/testdata/sonataflow-foreach.yaml b/api/v1alpha08/testdata/sonataflow-foreach.yaml deleted file mode 100644 index b6eb81a4..00000000 --- a/api/v1alpha08/testdata/sonataflow-foreach.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: foreach - annotations: - sonataflow.org/expressionLang: jq - sonataflow.org/version: "1.0" - sonataflow.org/description: An example of how to use for each state -spec: - flow: - start: start - functions: - - name: printMessage - type: custom - operation: sysout - - name: increase - type: expression - operation: ".item + 1" - states: - - name: start - type: foreach - iterationParam: item - inputCollection: ".input" - outputCollection: ".output" - stateDataFilter: - output: "{output: .output}" - actions: - - name: increase - functionRef: - refName: increase - - name: printAction - functionRef: - refName: printMessage - arguments: - message: ".item" - end: true diff --git a/api/v1alpha08/testdata/sonataflow-invalid.yaml b/api/v1alpha08/testdata/sonataflow-invalid.yaml deleted file mode 100644 index 23fffd80..00000000 --- a/api/v1alpha08/testdata/sonataflow-invalid.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: invalid - annotations: - sonataflow.org/expressionLang: jq - sonataflow.org/version: "1.0" - sonataflow.org/description: A valid workflow should have states. -spec: - flow: {} diff --git a/api/v1alpha08/zz_generated.deepcopy.go b/api/v1alpha08/zz_generated.deepcopy.go deleted file mode 100644 index 807168c4..00000000 --- a/api/v1alpha08/zz_generated.deepcopy.go +++ /dev/null @@ -1,1559 +0,0 @@ -//go:build !ignore_autogenerated - -/* - * Copyright 2026 The Kubesmarts 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 controller-gen. DO NOT EDIT. - -package v1alpha08 - -import ( - "github.com/serverlessworkflow/sdk-go/v2/model" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/intstr" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BuildPlatformConfig) DeepCopyInto(out *BuildPlatformConfig) { - *out = *in - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(metav1.Duration) - **out = **in - } - if in.BuildStrategyOptions != nil { - in, out := &in.BuildStrategyOptions, &out.BuildStrategyOptions - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - out.Registry = in.Registry -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildPlatformConfig. -func (in *BuildPlatformConfig) DeepCopy() *BuildPlatformConfig { - if in == nil { - return nil - } - out := new(BuildPlatformConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BuildPlatformSpec) DeepCopyInto(out *BuildPlatformSpec) { - *out = *in - in.Template.DeepCopyInto(&out.Template) - in.Config.DeepCopyInto(&out.Config) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildPlatformSpec. -func (in *BuildPlatformSpec) DeepCopy() *BuildPlatformSpec { - if in == nil { - return nil - } - out := new(BuildPlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BuildTemplate) DeepCopyInto(out *BuildTemplate) { - *out = *in - out.Timeout = in.Timeout - in.Resources.DeepCopyInto(&out.Resources) - if in.Arguments != nil { - in, out := &in.Arguments, &out.Arguments - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.BuildArgs != nil { - in, out := &in.BuildArgs, &out.BuildArgs - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Envs != nil { - in, out := &in.Envs, &out.Envs - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildTemplate. -func (in *BuildTemplate) DeepCopy() *BuildTemplate { - if in == nil { - return nil - } - out := new(BuildTemplate) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigMapWorkflowResource) DeepCopyInto(out *ConfigMapWorkflowResource) { - *out = *in - out.ConfigMap = in.ConfigMap -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapWorkflowResource. -func (in *ConfigMapWorkflowResource) DeepCopy() *ConfigMapWorkflowResource { - if in == nil { - return nil - } - out := new(ConfigMapWorkflowResource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerSpec) DeepCopyInto(out *ContainerSpec) { - *out = *in - if in.Command != nil { - in, out := &in.Command, &out.Command - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Args != nil { - in, out := &in.Args, &out.Args - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]v1.ContainerPort, len(*in)) - copy(*out, *in) - } - if in.EnvFrom != nil { - in, out := &in.EnvFrom, &out.EnvFrom - *out = make([]v1.EnvFromSource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Env != nil { - in, out := &in.Env, &out.Env - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.Resources.DeepCopyInto(&out.Resources) - if in.ResizePolicy != nil { - in, out := &in.ResizePolicy, &out.ResizePolicy - *out = make([]v1.ContainerResizePolicy, len(*in)) - copy(*out, *in) - } - if in.VolumeMounts != nil { - in, out := &in.VolumeMounts, &out.VolumeMounts - *out = make([]v1.VolumeMount, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.VolumeDevices != nil { - in, out := &in.VolumeDevices, &out.VolumeDevices - *out = make([]v1.VolumeDevice, len(*in)) - copy(*out, *in) - } - if in.LivenessProbe != nil { - in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(v1.Probe) - (*in).DeepCopyInto(*out) - } - if in.ReadinessProbe != nil { - in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(v1.Probe) - (*in).DeepCopyInto(*out) - } - if in.StartupProbe != nil { - in, out := &in.StartupProbe, &out.StartupProbe - *out = new(v1.Probe) - (*in).DeepCopyInto(*out) - } - if in.Lifecycle != nil { - in, out := &in.Lifecycle, &out.Lifecycle - *out = new(v1.Lifecycle) - (*in).DeepCopyInto(*out) - } - if in.SecurityContext != nil { - in, out := &in.SecurityContext, &out.SecurityContext - *out = new(v1.SecurityContext) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerSpec. -func (in *ContainerSpec) DeepCopy() *ContainerSpec { - if in == nil { - return nil - } - out := new(ContainerSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataIndexServiceSpec) DeepCopyInto(out *DataIndexServiceSpec) { - *out = *in - in.ServiceSpec.DeepCopyInto(&out.ServiceSpec) - if in.Source != nil { - in, out := &in.Source, &out.Source - *out = new(duckv1.Destination) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataIndexServiceSpec. -func (in *DataIndexServiceSpec) DeepCopy() *DataIndexServiceSpec { - if in == nil { - return nil - } - out := new(DataIndexServiceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DevModePlatformSpec) DeepCopyInto(out *DevModePlatformSpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DevModePlatformSpec. -func (in *DevModePlatformSpec) DeepCopy() *DevModePlatformSpec { - if in == nil { - return nil - } - out := new(DevModePlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Flow) DeepCopyInto(out *Flow) { - *out = *in - if in.Start != nil { - in, out := &in.Start, &out.Start - *out = new(model.Start) - (*in).DeepCopyInto(*out) - } - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.DataInputSchema != nil { - in, out := &in.DataInputSchema, &out.DataInputSchema - *out = new(model.DataInputSchema) - (*in).DeepCopyInto(*out) - } - if in.Secrets != nil { - in, out := &in.Secrets, &out.Secrets - *out = make(model.Secrets, len(*in)) - copy(*out, *in) - } - if in.Constants != nil { - in, out := &in.Constants, &out.Constants - *out = new(model.Constants) - (*in).DeepCopyInto(*out) - } - if in.Timeouts != nil { - in, out := &in.Timeouts, &out.Timeouts - *out = new(model.Timeouts) - (*in).DeepCopyInto(*out) - } - if in.Errors != nil { - in, out := &in.Errors, &out.Errors - *out = make(model.Errors, len(*in)) - copy(*out, *in) - } - if in.Metadata != nil { - in, out := &in.Metadata, &out.Metadata - *out = make(model.Metadata, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = make(model.Auths, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.States != nil { - in, out := &in.States, &out.States - *out = make([]model.State, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Events != nil { - in, out := &in.Events, &out.Events - *out = make(model.Events, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Functions != nil { - in, out := &in.Functions, &out.Functions - *out = make(model.Functions, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Retries != nil { - in, out := &in.Retries, &out.Retries - *out = make(model.Retries, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flow. -func (in *Flow) DeepCopy() *Flow { - if in == nil { - return nil - } - out := new(Flow) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FlowPodTemplateSpec) DeepCopyInto(out *FlowPodTemplateSpec) { - *out = *in - in.Container.DeepCopyInto(&out.Container) - in.PodSpec.DeepCopyInto(&out.PodSpec) - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas - *out = new(int32) - **out = **in - } - if in.PodDisruptionBudget != nil { - in, out := &in.PodDisruptionBudget, &out.PodDisruptionBudget - *out = new(PodDisruptionBudgetSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlowPodTemplateSpec. -func (in *FlowPodTemplateSpec) DeepCopy() *FlowPodTemplateSpec { - if in == nil { - return nil - } - out := new(FlowPodTemplateSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JobServiceServiceSpec) DeepCopyInto(out *JobServiceServiceSpec) { - *out = *in - in.ServiceSpec.DeepCopyInto(&out.ServiceSpec) - if in.Sink != nil { - in, out := &in.Sink, &out.Sink - *out = new(duckv1.Destination) - (*in).DeepCopyInto(*out) - } - if in.Source != nil { - in, out := &in.Source, &out.Source - *out = new(duckv1.Destination) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobServiceServiceSpec. -func (in *JobServiceServiceSpec) DeepCopy() *JobServiceServiceSpec { - if in == nil { - return nil - } - out := new(JobServiceServiceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PersistenceOptionsSpec) DeepCopyInto(out *PersistenceOptionsSpec) { - *out = *in - if in.PostgreSQL != nil { - in, out := &in.PostgreSQL, &out.PostgreSQL - *out = new(PersistencePostgreSQL) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistenceOptionsSpec. -func (in *PersistenceOptionsSpec) DeepCopy() *PersistenceOptionsSpec { - if in == nil { - return nil - } - out := new(PersistenceOptionsSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PersistencePostgreSQL) DeepCopyInto(out *PersistencePostgreSQL) { - *out = *in - out.SecretRef = in.SecretRef - if in.ServiceRef != nil { - in, out := &in.ServiceRef, &out.ServiceRef - *out = new(PostgreSQLServiceOptions) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistencePostgreSQL. -func (in *PersistencePostgreSQL) DeepCopy() *PersistencePostgreSQL { - if in == nil { - return nil - } - out := new(PersistencePostgreSQL) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformEventingSpec) DeepCopyInto(out *PlatformEventingSpec) { - *out = *in - if in.Broker != nil { - in, out := &in.Broker, &out.Broker - *out = new(duckv1.Destination) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformEventingSpec. -func (in *PlatformEventingSpec) DeepCopy() *PlatformEventingSpec { - if in == nil { - return nil - } - out := new(PlatformEventingSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformMonitoringOptionsSpec) DeepCopyInto(out *PlatformMonitoringOptionsSpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformMonitoringOptionsSpec. -func (in *PlatformMonitoringOptionsSpec) DeepCopy() *PlatformMonitoringOptionsSpec { - if in == nil { - return nil - } - out := new(PlatformMonitoringOptionsSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformPersistenceOptionsSpec) DeepCopyInto(out *PlatformPersistenceOptionsSpec) { - *out = *in - if in.PostgreSQL != nil { - in, out := &in.PostgreSQL, &out.PostgreSQL - *out = new(PlatformPersistencePostgreSQL) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformPersistenceOptionsSpec. -func (in *PlatformPersistenceOptionsSpec) DeepCopy() *PlatformPersistenceOptionsSpec { - if in == nil { - return nil - } - out := new(PlatformPersistenceOptionsSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformPersistencePostgreSQL) DeepCopyInto(out *PlatformPersistencePostgreSQL) { - *out = *in - out.SecretRef = in.SecretRef - if in.ServiceRef != nil { - in, out := &in.ServiceRef, &out.ServiceRef - *out = new(SQLServiceOptions) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformPersistencePostgreSQL. -func (in *PlatformPersistencePostgreSQL) DeepCopy() *PlatformPersistencePostgreSQL { - if in == nil { - return nil - } - out := new(PlatformPersistencePostgreSQL) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformServiceRefStatus) DeepCopyInto(out *PlatformServiceRefStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformServiceRefStatus. -func (in *PlatformServiceRefStatus) DeepCopy() *PlatformServiceRefStatus { - if in == nil { - return nil - } - out := new(PlatformServiceRefStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformServicesStatus) DeepCopyInto(out *PlatformServicesStatus) { - *out = *in - if in.DataIndexRef != nil { - in, out := &in.DataIndexRef, &out.DataIndexRef - *out = new(PlatformServiceRefStatus) - **out = **in - } - if in.JobServiceRef != nil { - in, out := &in.JobServiceRef, &out.JobServiceRef - *out = new(PlatformServiceRefStatus) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformServicesStatus. -func (in *PlatformServicesStatus) DeepCopy() *PlatformServicesStatus { - if in == nil { - return nil - } - out := new(PlatformServicesStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodDisruptionBudgetSpec) DeepCopyInto(out *PodDisruptionBudgetSpec) { - *out = *in - 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 PodDisruptionBudgetSpec. -func (in *PodDisruptionBudgetSpec) DeepCopy() *PodDisruptionBudgetSpec { - if in == nil { - return nil - } - out := new(PodDisruptionBudgetSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodSpec) DeepCopyInto(out *PodSpec) { - *out = *in - if in.Volumes != nil { - in, out := &in.Volumes, &out.Volumes - *out = make([]v1.Volume, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.InitContainers != nil { - in, out := &in.InitContainers, &out.InitContainers - *out = make([]v1.Container, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Containers != nil { - in, out := &in.Containers, &out.Containers - *out = make([]v1.Container, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.TerminationGracePeriodSeconds != nil { - in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds - *out = new(int64) - **out = **in - } - if in.ActiveDeadlineSeconds != nil { - in, out := &in.ActiveDeadlineSeconds, &out.ActiveDeadlineSeconds - *out = new(int64) - **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.AutomountServiceAccountToken != nil { - in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken - *out = new(bool) - **out = **in - } - if in.ShareProcessNamespace != nil { - in, out := &in.ShareProcessNamespace, &out.ShareProcessNamespace - *out = new(bool) - **out = **in - } - if in.SecurityContext != nil { - in, out := &in.SecurityContext, &out.SecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.ImagePullSecrets != nil { - in, out := &in.ImagePullSecrets, &out.ImagePullSecrets - *out = make([]v1.LocalObjectReference, len(*in)) - copy(*out, *in) - } - if in.Affinity != nil { - in, out := &in.Affinity, &out.Affinity - *out = new(v1.Affinity) - (*in).DeepCopyInto(*out) - } - 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]) - } - } - if in.HostAliases != nil { - in, out := &in.HostAliases, &out.HostAliases - *out = make([]v1.HostAlias, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Priority != nil { - in, out := &in.Priority, &out.Priority - *out = new(int32) - **out = **in - } - if in.DNSConfig != nil { - in, out := &in.DNSConfig, &out.DNSConfig - *out = new(v1.PodDNSConfig) - (*in).DeepCopyInto(*out) - } - if in.ReadinessGates != nil { - in, out := &in.ReadinessGates, &out.ReadinessGates - *out = make([]v1.PodReadinessGate, len(*in)) - copy(*out, *in) - } - if in.RuntimeClassName != nil { - in, out := &in.RuntimeClassName, &out.RuntimeClassName - *out = new(string) - **out = **in - } - if in.EnableServiceLinks != nil { - in, out := &in.EnableServiceLinks, &out.EnableServiceLinks - *out = new(bool) - **out = **in - } - if in.PreemptionPolicy != nil { - in, out := &in.PreemptionPolicy, &out.PreemptionPolicy - *out = new(v1.PreemptionPolicy) - **out = **in - } - if in.Overhead != nil { - in, out := &in.Overhead, &out.Overhead - *out = make(v1.ResourceList, len(*in)) - for key, val := range *in { - (*out)[key] = val.DeepCopy() - } - } - if in.TopologySpreadConstraints != nil { - in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints - *out = make([]v1.TopologySpreadConstraint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.SetHostnameAsFQDN != nil { - in, out := &in.SetHostnameAsFQDN, &out.SetHostnameAsFQDN - *out = new(bool) - **out = **in - } - if in.OS != nil { - in, out := &in.OS, &out.OS - *out = new(v1.PodOS) - **out = **in - } - if in.HostUsers != nil { - in, out := &in.HostUsers, &out.HostUsers - *out = new(bool) - **out = **in - } - if in.SchedulingGates != nil { - in, out := &in.SchedulingGates, &out.SchedulingGates - *out = make([]v1.PodSchedulingGate, len(*in)) - copy(*out, *in) - } - if in.ResourceClaims != nil { - in, out := &in.ResourceClaims, &out.ResourceClaims - *out = make([]v1.PodResourceClaim, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSpec. -func (in *PodSpec) DeepCopy() *PodSpec { - if in == nil { - return nil - } - out := new(PodSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodTemplateSpec) DeepCopyInto(out *PodTemplateSpec) { - *out = *in - in.Container.DeepCopyInto(&out.Container) - in.PodSpec.DeepCopyInto(&out.PodSpec) - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas - *out = new(int32) - **out = **in - } - if in.PodDisruptionBudget != nil { - in, out := &in.PodDisruptionBudget, &out.PodDisruptionBudget - *out = new(PodDisruptionBudgetSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodTemplateSpec. -func (in *PodTemplateSpec) DeepCopy() *PodTemplateSpec { - if in == nil { - return nil - } - out := new(PodTemplateSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostgreSQLSecretOptions) DeepCopyInto(out *PostgreSQLSecretOptions) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLSecretOptions. -func (in *PostgreSQLSecretOptions) DeepCopy() *PostgreSQLSecretOptions { - if in == nil { - return nil - } - out := new(PostgreSQLSecretOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostgreSQLServiceOptions) DeepCopyInto(out *PostgreSQLServiceOptions) { - *out = *in - if in.SQLServiceOptions != nil { - in, out := &in.SQLServiceOptions, &out.SQLServiceOptions - *out = new(SQLServiceOptions) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLServiceOptions. -func (in *PostgreSQLServiceOptions) DeepCopy() *PostgreSQLServiceOptions { - if in == nil { - return nil - } - out := new(PostgreSQLServiceOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PropertyPlatformSpec) DeepCopyInto(out *PropertyPlatformSpec) { - *out = *in - if in.Flow != nil { - in, out := &in.Flow, &out.Flow - *out = make([]PropertyVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PropertyPlatformSpec. -func (in *PropertyPlatformSpec) DeepCopy() *PropertyPlatformSpec { - if in == nil { - return nil - } - out := new(PropertyPlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PropertyVar) DeepCopyInto(out *PropertyVar) { - *out = *in - if in.ValueFrom != nil { - in, out := &in.ValueFrom, &out.ValueFrom - *out = new(PropertyVarSource) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PropertyVar. -func (in *PropertyVar) DeepCopy() *PropertyVar { - if in == nil { - return nil - } - out := new(PropertyVar) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PropertyVarSource) DeepCopyInto(out *PropertyVarSource) { - *out = *in - if in.ConfigMapKeyRef != nil { - in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef - *out = new(v1.ConfigMapKeySelector) - (*in).DeepCopyInto(*out) - } - if in.SecretKeyRef != nil { - in, out := &in.SecretKeyRef, &out.SecretKeyRef - *out = new(v1.SecretKeySelector) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PropertyVarSource. -func (in *PropertyVarSource) DeepCopy() *PropertyVarSource { - if in == nil { - return nil - } - out := new(PropertyVarSource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RegistrySpec) DeepCopyInto(out *RegistrySpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrySpec. -func (in *RegistrySpec) DeepCopy() *RegistrySpec { - if in == nil { - return nil - } - out := new(RegistrySpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SQLServiceOptions) DeepCopyInto(out *SQLServiceOptions) { - *out = *in - if in.Port != nil { - in, out := &in.Port, &out.Port - *out = new(int) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SQLServiceOptions. -func (in *SQLServiceOptions) DeepCopy() *SQLServiceOptions { - if in == nil { - return nil - } - out := new(SQLServiceOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { - *out = *in - if in.Enabled != nil { - in, out := &in.Enabled, &out.Enabled - *out = new(bool) - **out = **in - } - if in.Persistence != nil { - in, out := &in.Persistence, &out.Persistence - *out = new(PersistenceOptionsSpec) - (*in).DeepCopyInto(*out) - } - in.PodTemplate.DeepCopyInto(&out.PodTemplate) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. -func (in *ServiceSpec) DeepCopy() *ServiceSpec { - if in == nil { - return nil - } - out := new(ServiceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServicesPlatformSpec) DeepCopyInto(out *ServicesPlatformSpec) { - *out = *in - if in.DataIndex != nil { - in, out := &in.DataIndex, &out.DataIndex - *out = new(DataIndexServiceSpec) - (*in).DeepCopyInto(*out) - } - if in.JobService != nil { - in, out := &in.JobService, &out.JobService - *out = new(JobServiceServiceSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicesPlatformSpec. -func (in *ServicesPlatformSpec) DeepCopy() *ServicesPlatformSpec { - if in == nil { - return nil - } - out := new(ServicesPlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlow) DeepCopyInto(out *SonataFlow) { - *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 SonataFlow. -func (in *SonataFlow) DeepCopy() *SonataFlow { - if in == nil { - return nil - } - out := new(SonataFlow) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlow) 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 *SonataFlowBuild) DeepCopyInto(out *SonataFlowBuild) { - *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 SonataFlowBuild. -func (in *SonataFlowBuild) DeepCopy() *SonataFlowBuild { - if in == nil { - return nil - } - out := new(SonataFlowBuild) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowBuild) 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 *SonataFlowBuildList) DeepCopyInto(out *SonataFlowBuildList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]SonataFlowBuild, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowBuildList. -func (in *SonataFlowBuildList) DeepCopy() *SonataFlowBuildList { - if in == nil { - return nil - } - out := new(SonataFlowBuildList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowBuildList) 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 *SonataFlowBuildSpec) DeepCopyInto(out *SonataFlowBuildSpec) { - *out = *in - in.BuildTemplate.DeepCopyInto(&out.BuildTemplate) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowBuildSpec. -func (in *SonataFlowBuildSpec) DeepCopy() *SonataFlowBuildSpec { - if in == nil { - return nil - } - out := new(SonataFlowBuildSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowBuildStatus) DeepCopyInto(out *SonataFlowBuildStatus) { - *out = *in - in.InnerBuild.DeepCopyInto(&out.InnerBuild) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowBuildStatus. -func (in *SonataFlowBuildStatus) DeepCopy() *SonataFlowBuildStatus { - if in == nil { - return nil - } - out := new(SonataFlowBuildStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowClusterPlatform) DeepCopyInto(out *SonataFlowClusterPlatform) { - *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 SonataFlowClusterPlatform. -func (in *SonataFlowClusterPlatform) DeepCopy() *SonataFlowClusterPlatform { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatform) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowClusterPlatform) 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 *SonataFlowClusterPlatformCapSpec) DeepCopyInto(out *SonataFlowClusterPlatformCapSpec) { - *out = *in - if in.Workflows != nil { - in, out := &in.Workflows, &out.Workflows - *out = make([]WorkFlowCapability, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformCapSpec. -func (in *SonataFlowClusterPlatformCapSpec) DeepCopy() *SonataFlowClusterPlatformCapSpec { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatformCapSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowClusterPlatformList) DeepCopyInto(out *SonataFlowClusterPlatformList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]SonataFlowClusterPlatform, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformList. -func (in *SonataFlowClusterPlatformList) DeepCopy() *SonataFlowClusterPlatformList { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatformList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowClusterPlatformList) 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 *SonataFlowClusterPlatformRefStatus) DeepCopyInto(out *SonataFlowClusterPlatformRefStatus) { - *out = *in - out.PlatformRef = in.PlatformRef - if in.Services != nil { - in, out := &in.Services, &out.Services - *out = new(PlatformServicesStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformRefStatus. -func (in *SonataFlowClusterPlatformRefStatus) DeepCopy() *SonataFlowClusterPlatformRefStatus { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatformRefStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowClusterPlatformSpec) DeepCopyInto(out *SonataFlowClusterPlatformSpec) { - *out = *in - out.PlatformRef = in.PlatformRef - if in.Capabilities != nil { - in, out := &in.Capabilities, &out.Capabilities - *out = new(SonataFlowClusterPlatformCapSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformSpec. -func (in *SonataFlowClusterPlatformSpec) DeepCopy() *SonataFlowClusterPlatformSpec { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowClusterPlatformStatus) DeepCopyInto(out *SonataFlowClusterPlatformStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformStatus. -func (in *SonataFlowClusterPlatformStatus) DeepCopy() *SonataFlowClusterPlatformStatus { - if in == nil { - return nil - } - out := new(SonataFlowClusterPlatformStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowList) DeepCopyInto(out *SonataFlowList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]SonataFlow, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowList. -func (in *SonataFlowList) DeepCopy() *SonataFlowList { - if in == nil { - return nil - } - out := new(SonataFlowList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowList) 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 *SonataFlowPlatform) DeepCopyInto(out *SonataFlowPlatform) { - *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 SonataFlowPlatform. -func (in *SonataFlowPlatform) DeepCopy() *SonataFlowPlatform { - if in == nil { - return nil - } - out := new(SonataFlowPlatform) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowPlatform) 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 *SonataFlowPlatformDBMigrationPhase) DeepCopyInto(out *SonataFlowPlatformDBMigrationPhase) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformDBMigrationPhase. -func (in *SonataFlowPlatformDBMigrationPhase) DeepCopy() *SonataFlowPlatformDBMigrationPhase { - if in == nil { - return nil - } - out := new(SonataFlowPlatformDBMigrationPhase) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowPlatformList) DeepCopyInto(out *SonataFlowPlatformList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]SonataFlowPlatform, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformList. -func (in *SonataFlowPlatformList) DeepCopy() *SonataFlowPlatformList { - if in == nil { - return nil - } - out := new(SonataFlowPlatformList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SonataFlowPlatformList) 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 *SonataFlowPlatformRef) DeepCopyInto(out *SonataFlowPlatformRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformRef. -func (in *SonataFlowPlatformRef) DeepCopy() *SonataFlowPlatformRef { - if in == nil { - return nil - } - out := new(SonataFlowPlatformRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowPlatformSpec) DeepCopyInto(out *SonataFlowPlatformSpec) { - *out = *in - in.Build.DeepCopyInto(&out.Build) - out.DevMode = in.DevMode - if in.Services != nil { - in, out := &in.Services, &out.Services - *out = new(ServicesPlatformSpec) - (*in).DeepCopyInto(*out) - } - if in.Eventing != nil { - in, out := &in.Eventing, &out.Eventing - *out = new(PlatformEventingSpec) - (*in).DeepCopyInto(*out) - } - if in.Persistence != nil { - in, out := &in.Persistence, &out.Persistence - *out = new(PlatformPersistenceOptionsSpec) - (*in).DeepCopyInto(*out) - } - if in.Properties != nil { - in, out := &in.Properties, &out.Properties - *out = new(PropertyPlatformSpec) - (*in).DeepCopyInto(*out) - } - if in.Monitoring != nil { - in, out := &in.Monitoring, &out.Monitoring - *out = new(PlatformMonitoringOptionsSpec) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformSpec. -func (in *SonataFlowPlatformSpec) DeepCopy() *SonataFlowPlatformSpec { - if in == nil { - return nil - } - out := new(SonataFlowPlatformSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowPlatformStatus) DeepCopyInto(out *SonataFlowPlatformStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - if in.Info != nil { - in, out := &in.Info, &out.Info - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.ClusterPlatformRef != nil { - in, out := &in.ClusterPlatformRef, &out.ClusterPlatformRef - *out = new(SonataFlowClusterPlatformRefStatus) - (*in).DeepCopyInto(*out) - } - if in.Triggers != nil { - in, out := &in.Triggers, &out.Triggers - *out = make([]SonataFlowPlatformTriggerRef, len(*in)) - copy(*out, *in) - } - if in.SonataFlowPlatformDBMigrationPhase != nil { - in, out := &in.SonataFlowPlatformDBMigrationPhase, &out.SonataFlowPlatformDBMigrationPhase - *out = new(SonataFlowPlatformDBMigrationPhase) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformStatus. -func (in *SonataFlowPlatformStatus) DeepCopy() *SonataFlowPlatformStatus { - if in == nil { - return nil - } - out := new(SonataFlowPlatformStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowPlatformTriggerRef) DeepCopyInto(out *SonataFlowPlatformTriggerRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowPlatformTriggerRef. -func (in *SonataFlowPlatformTriggerRef) DeepCopy() *SonataFlowPlatformTriggerRef { - if in == nil { - return nil - } - out := new(SonataFlowPlatformTriggerRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowSourceSpec) DeepCopyInto(out *SonataFlowSourceSpec) { - *out = *in - in.Destination.DeepCopyInto(&out.Destination) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowSourceSpec. -func (in *SonataFlowSourceSpec) DeepCopy() *SonataFlowSourceSpec { - if in == nil { - return nil - } - out := new(SonataFlowSourceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowSpec) DeepCopyInto(out *SonataFlowSpec) { - *out = *in - in.Flow.DeepCopyInto(&out.Flow) - in.Resources.DeepCopyInto(&out.Resources) - in.PodTemplate.DeepCopyInto(&out.PodTemplate) - if in.Persistence != nil { - in, out := &in.Persistence, &out.Persistence - *out = new(PersistenceOptionsSpec) - (*in).DeepCopyInto(*out) - } - if in.Sink != nil { - in, out := &in.Sink, &out.Sink - *out = new(duckv1.Destination) - (*in).DeepCopyInto(*out) - } - if in.Sources != nil { - in, out := &in.Sources, &out.Sources - *out = make([]SonataFlowSourceSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowSpec. -func (in *SonataFlowSpec) DeepCopy() *SonataFlowSpec { - if in == nil { - return nil - } - out := new(SonataFlowSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowStatus) DeepCopyInto(out *SonataFlowStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - in.Address.DeepCopyInto(&out.Address) - in.LastTimeRecoverAttempt.DeepCopyInto(&out.LastTimeRecoverAttempt) - if in.Endpoint != nil { - in, out := &in.Endpoint, &out.Endpoint - *out = new(apis.URL) - (*in).DeepCopyInto(*out) - } - if in.Services != nil { - in, out := &in.Services, &out.Services - *out = new(PlatformServicesStatus) - (*in).DeepCopyInto(*out) - } - if in.Platform != nil { - in, out := &in.Platform, &out.Platform - *out = new(SonataFlowPlatformRef) - **out = **in - } - if in.Triggers != nil { - in, out := &in.Triggers, &out.Triggers - *out = make([]SonataFlowTriggerRef, len(*in)) - copy(*out, *in) - } - if in.LastTimeFinalizerAttempt != nil { - in, out := &in.LastTimeFinalizerAttempt, &out.LastTimeFinalizerAttempt - *out = (*in).DeepCopy() - } - if in.LastTimeStatusNotified != nil { - in, out := &in.LastTimeStatusNotified, &out.LastTimeStatusNotified - *out = (*in).DeepCopy() - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowStatus. -func (in *SonataFlowStatus) DeepCopy() *SonataFlowStatus { - if in == nil { - return nil - } - out := new(SonataFlowStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SonataFlowTriggerRef) DeepCopyInto(out *SonataFlowTriggerRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowTriggerRef. -func (in *SonataFlowTriggerRef) DeepCopy() *SonataFlowTriggerRef { - if in == nil { - return nil - } - out := new(SonataFlowTriggerRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *WorkflowResources) DeepCopyInto(out *WorkflowResources) { - *out = *in - if in.ConfigMaps != nil { - in, out := &in.ConfigMaps, &out.ConfigMaps - *out = make([]ConfigMapWorkflowResource, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowResources. -func (in *WorkflowResources) DeepCopy() *WorkflowResources { - if in == nil { - return nil - } - out := new(WorkflowResources) - in.DeepCopyInto(out) - return out -} diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index 7ef2ca38..8b8bbe04 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -1,25 +1,27 @@ //go:build !ignore_autogenerated /* - * Copyright 2026 The Kubesmarts 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. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 api +import () + // 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 diff --git a/bundle/README.md b/bundle/README.md deleted file mode 100644 index b1c18d34..00000000 --- a/bundle/README.md +++ /dev/null @@ -1,28 +0,0 @@ - - -# SonataFlow Operator Bundle - -To generate the files in [manifests](manifests) directory run from the project's root: - -```shell -make generate-all -make vet fmt -``` - -The file `sonataflow-operator.clusterserviceversion.yaml` will be generated as part of the outcome of this command. -This file has been removed from git since every time the command runs, it generates the attribute `createdAt`. diff --git a/bundle/metadata/annotations.yaml b/bundle/metadata/annotations.yaml deleted file mode 100644 index 7b6bd36a..00000000 --- a/bundle/metadata/annotations.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -annotations: - # Core bundle annotations. - operators.operatorframework.io.bundle.mediatype.v1: registry+v1 - operators.operatorframework.io.bundle.manifests.v1: manifests/ - operators.operatorframework.io.bundle.metadata.v1: metadata/ - operators.operatorframework.io.bundle.package.v1: sonataflow-operator - operators.operatorframework.io.bundle.channels.v1: stable - operators.operatorframework.io.bundle.channel.default.v1: stable - - operators.operatorframework.io.metrics.builder: operator-sdk-v1.35.0 - operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 - operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v3 - com.redhat.openshift.versions: v4.11 - - # Annotations for testing. - operators.operatorframework.io.test.mediatype.v1: scorecard+v1 - operators.operatorframework.io.test.config.v1: tests/scorecard/ diff --git a/bundle/tests/scorecard/config.yaml b/bundle/tests/scorecard/config.yaml deleted file mode 100644 index 62527e7e..00000000 --- a/bundle/tests/scorecard/config.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2026 The Kubesmarts 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. - -apiVersion: scorecard.operatorframework.io/v1alpha3 -kind: Configuration -metadata: - name: config -stages: -- parallel: true - tests: - - entrypoint: - - scorecard-test - - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.35.0 - labels: - suite: basic - test: basic-check-spec-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.35.0 - labels: - suite: olm - test: olm-bundle-validation-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.35.0 - labels: - suite: olm - test: olm-crds-have-validation-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.21.0 - labels: - suite: olm - test: olm-crds-have-resources-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.35.0 - labels: - suite: olm - test: olm-spec-descriptors-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.35.0 - labels: - suite: olm - test: olm-status-descriptors-test - storage: - spec: - mountPath: {} -storage: - spec: - mountPath: {} diff --git a/cli/DEPRECATED.md b/cli/DEPRECATED.md new file mode 100644 index 00000000..00b8dffc --- /dev/null +++ b/cli/DEPRECATED.md @@ -0,0 +1,41 @@ +# CLI Module - DEPRECATED + +## Status + +**This module is currently deprecated and excluded from the Logic Operator v2.0 refactoring.** + +## Background + +The Logic Operator is undergoing a major architectural overhaul from SonataFlow to Quarkus Flow (v2.0). +During this transition, the CLI module has been temporarily excluded from the codebase to: + +1. Avoid maintenance burden during the core operator refactoring +2. Allow time to properly assess CLI requirements in the v2.0 architecture +3. Prevent breaking changes to the CLI while the operator API evolves + +## Current State + +- **Build Status**: Excluded from `go.work` - will not compile with main operator +- **Maintenance**: No active development or bug fixes +- **Testing**: Excluded from CI/CD pipelines + +## Future + +The CLI's role and implementation will be reassessed after the v2.0 core operator work is complete. +Possible outcomes: + +- **Redesign**: CLI rebuilt to work with new v2.0 CRDs (LogicPlatform, LogicFlowDefinition, etc.) +- **Archive**: Deprecated permanently if CLI use cases are better served by kubectl/kustomize +- **Extract**: Moved to separate repository with independent lifecycle + +## Migration + +For users currently relying on the CLI: + +- Use `kubectl` and `kustomize` to manage Logic Operator v2.0 resources directly +- Existing CLI workflows will not be compatible with v2.0 operator + +## Related + +- [ADR-001: Logic Operator v2.0 Architecture](../adr/001-logic-operator-v2-architecture.md) +- [EPIC 0: Codebase Cleanup](https://github.com/kubesmarts/logic-operator/issues/3) diff --git a/cli/go.mod b/cli/go.mod index 230b0843..eeb9ee44 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -4,8 +4,6 @@ go 1.26.0 // Use local modules via go.work replace ( - github.com/kubesmarts/logic-operator/api => ../api - github.com/kubesmarts/logic-operator/workflowproj => ../workflowproj ) require ( @@ -15,8 +13,6 @@ require ( github.com/docker/go-connections v0.5.0 github.com/getkin/kin-openapi v0.131.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 - github.com/kubesmarts/logic-operator/api v0.0.0 - github.com/kubesmarts/logic-operator/workflowproj v0.0.0 github.com/ory/viper v1.7.5 github.com/spf13/afero v1.12.0 github.com/spf13/cobra v1.9.1 diff --git a/cli/go.sum b/cli/go.sum index b1314981..0d14119b 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -226,6 +226,7 @@ github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16A github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE= github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM= github.com/pb33f/libopenapi v0.10.1 h1:ADkXbW0CTrn7t6q3OQjY5bIFmFpovF8BF2WWPsWqZKs= @@ -336,6 +337,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= @@ -447,6 +449,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= k8s.io/api v0.31.6 h1:ocWG/UhC9Mqp5oEfYWy9wCddbZiZyBAFTlBt0LVlhDg= k8s.io/api v0.31.6/go.mod h1:i16xSiKMgVIVhsJMxfWq0mJbXA+Z7KhjPgYmwT41hl4= k8s.io/apiextensions-apiserver v0.31.6 h1:v9sqyWlrgFZpAPdEb/bEiXfM98TfSppwRF0X/uWKXh0= diff --git a/cmd/main.go b/cmd/main.go index 28535dc1..8c4ab06f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,52 +1,26 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 main import ( "crypto/tls" "flag" - "fmt" "os" - "time" - - "github.com/kubesmarts/logic-operator/api/version" - - "k8s.io/client-go/dynamic" - - "github.com/kubesmarts/logic-operator/internal/manager" - - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - "k8s.io/klog/v2/klogr" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - - "github.com/kubesmarts/logic-operator/internal/controller" - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/utils" - - ocputil "github.com/kubesmarts/logic-operator/utils/openshift" + "path/filepath" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -56,108 +30,161 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/certwatcher" "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/filters" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" - //+kubebuilder:scaffold:imports + logicv1 "github.com/kubesmarts/logic-operator/api/v1" + "github.com/kubesmarts/logic-operator/internal/controller" + // +kubebuilder:scaffold:imports ) var ( - scheme = runtime.NewScheme() + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") ) func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - utilruntime.Must(operatorapi.AddToScheme(scheme)) - utilruntime.Must(sourcesv1.AddToScheme(scheme)) - utilruntime.Must(eventingv1.AddToScheme(scheme)) - utilruntime.Must(servingv1.AddToScheme(scheme)) - utilruntime.Must(prometheus.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme + + utilruntime.Must(logicv1.AddToScheme(scheme)) + // +kubebuilder:scaffold:scheme } +// nolint:gocyclo func main() { var metricsAddr string + var metricsCertPath, metricsCertName, metricsCertKey string + var webhookCertPath, webhookCertName, webhookCertKey string var enableLeaderElection bool - var leaseDuration *time.Duration - var renewDeadline *time.Duration - var retryPeriod *time.Duration - var qps *float64 - var burst *int var probeAddr string var secureMetrics bool var enableHTTP2 bool - var controllerCfgPath string - klog.InitFlags(nil) - flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + var tlsOpts []func(*tls.Config) + flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ + "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") - // Flags for leader election tuning, resilient default values for production. - leaseDuration = flag.Duration("lease-duration", 60*time.Second, "Leader election lease duration") - renewDeadline = flag.Duration("renew-deadline", 40*time.Second, "Leader election renew deadline") - retryPeriod = flag.Duration("retry-period", 15*time.Second, "Leader election retry period") - - // Flags for tuning client-go throttling - // 20 / 50 Very light operators - // 50 / 100 General-purpose OLM operators - // 100 / 200 Operators managing many CRDs or watching many namespaces - // 200 / 400 Extremely chatty operators (cluster-wide + many controllers) - qps = flag.Float64("qps", 50, "Maximum average QPS for Kubernetes client-go") - burst = flag.Int("burst", 100, "Maximum burst for Kubernetes client-go") - - flag.BoolVar(&secureMetrics, "metrics-secure", false, - "If set the metrics endpoint is served securely") + flag.BoolVar(&secureMetrics, "metrics-secure", true, + "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.") + flag.StringVar(&webhookCertPath, "webhook-cert-path", "", "The directory that contains the webhook certificate.") + flag.StringVar(&webhookCertName, "webhook-cert-name", "tls.crt", "The name of the webhook certificate file.") + flag.StringVar(&webhookCertKey, "webhook-cert-key", "tls.key", "The name of the webhook key file.") + flag.StringVar(&metricsCertPath, "metrics-cert-path", "", + "The directory that contains the metrics server certificate.") + flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.") + flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.") flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") - flag.StringVar(&controllerCfgPath, "controller-cfg-path", "", "The controller config file path.") + opts := zap.Options{ + Development: true, + } + opts.BindFlags(flag.CommandLine) flag.Parse() - klog.InfoS("leader election configuration", - "leader-elect", enableLeaderElection, - "lease-duration", leaseDuration, - "renew-deadline", renewDeadline, - "retry-period", retryPeriod) - - klog.InfoS("client-go throttling configuration", - "qps", qps, - "burst", burst) - - manager.SetOperatorStartTime() - - ctrl.SetLogger(klogr.New().WithName(controller.ComponentName)) + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) // if the enable-http2 flag is false (the default), http/2 should be disabled // due to its vulnerabilities. More specifically, disabling http/2 will // prevent from being vulnerable to the HTTP/2 Stream Cancellation and - // Rapid Reset CVEs. For development information see: + // Rapid Reset CVEs. For more information see: // - https://github.com/advisories/GHSA-qppj-fm5r-hxr3 // - https://github.com/advisories/GHSA-4374-p667-p6c8 disableHTTP2 := func(c *tls.Config) { - klog.V(log.I).Info("disabling http/2") + setupLog.Info("disabling http/2") c.NextProtos = []string{"http/1.1"} } - tlsOpts := []func(*tls.Config){} if !enableHTTP2 { tlsOpts = append(tlsOpts, disableHTTP2) } - config := ctrl.GetConfigOrDie() - config.QPS = float32(*qps) - config.Burst = *burst - mgr, err := ctrl.NewManager(config, ctrl.Options{ - Scheme: scheme, - Metrics: metricsserver.Options{ - BindAddress: metricsAddr, - SecureServing: secureMetrics, - TLSOpts: tlsOpts, - }, + // Create watchers for metrics and webhooks certificates + var metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher + + // Initial webhook TLS options + webhookTLSOpts := tlsOpts + + if len(webhookCertPath) > 0 { + setupLog.Info("Initializing webhook certificate watcher using provided certificates", + "webhook-cert-path", webhookCertPath, "webhook-cert-name", webhookCertName, "webhook-cert-key", webhookCertKey) + + var err error + webhookCertWatcher, err = certwatcher.New( + filepath.Join(webhookCertPath, webhookCertName), + filepath.Join(webhookCertPath, webhookCertKey), + ) + if err != nil { + setupLog.Error(err, "Failed to initialize webhook certificate watcher") + os.Exit(1) + } + + webhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) { + config.GetCertificate = webhookCertWatcher.GetCertificate + }) + } + + webhookServer := webhook.NewServer(webhook.Options{ + TLSOpts: webhookTLSOpts, + }) + + // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server. + // More info: + // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server + // - https://book.kubebuilder.io/reference/metrics.html + metricsServerOptions := metricsserver.Options{ + BindAddress: metricsAddr, + SecureServing: secureMetrics, + TLSOpts: tlsOpts, + } + + if secureMetrics { + // FilterProvider is used to protect the metrics endpoint with authn/authz. + // These configurations ensure that only authorized users and service accounts + // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info: + // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/filters#WithAuthenticationAndAuthorization + metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization + } + + // If the certificate is not specified, controller-runtime will automatically + // generate self-signed certificates for the metrics server. While convenient for development and testing, + // this setup is not recommended for production. + // + // TODO(user): If you enable certManager, uncomment the following lines: + // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates + // managed by cert-manager for the metrics server. + // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification. + if len(metricsCertPath) > 0 { + setupLog.Info("Initializing metrics certificate watcher using provided certificates", + "metrics-cert-path", metricsCertPath, "metrics-cert-name", metricsCertName, "metrics-cert-key", metricsCertKey) + + var err error + metricsCertWatcher, err = certwatcher.New( + filepath.Join(metricsCertPath, metricsCertName), + filepath.Join(metricsCertPath, metricsCertKey), + ) + if err != nil { + setupLog.Error(err, "to initialize metrics certificate watcher", "error", err) + os.Exit(1) + } + + metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) { + config.GetCertificate = metricsCertWatcher.GetCertificate + }) + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + Metrics: metricsServerOptions, + WebhookServer: webhookServer, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, - LeaderElectionID: "1be5e57d.kie.org", + LeaderElectionID: "07e8f64f.kubesmarts.org", // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly @@ -169,92 +196,70 @@ func main() { // if you are doing or is intended to do any operation such as perform cleanups // after the manager stops then its usage might be unsafe. // LeaderElectionReleaseOnCancel: true, - LeaseDuration: leaseDuration, - RenewDeadline: renewDeadline, - RetryPeriod: retryPeriod, }) if err != nil { - klog.V(log.E).ErrorS(err, "unable to start manager") + setupLog.Error(err, "unable to start manager") os.Exit(1) } - // Set global assessors - utils.SetIsOpenShift(mgr.GetConfig()) - utils.SetClient(mgr.GetClient()) - cli, err := dynamic.NewForConfig(mgr.GetConfig()) - if err != nil { - // shouldn't fail, since config is provided by the cluster, if fails, SetIsOpenShift should probably fail before. - panic(fmt.Sprintf("Impossible to get new dynamic client for config to support controller operations: %s", err)) - } - utils.SetDynamicClient(cli) - - // Fail fast, we can change this behavior in the future to read from defaults instead. - if _, err = cfg.InitializeControllersCfgAt(controllerCfgPath); err != nil { - klog.V(log.E).ErrorS(err, "unable to read controllers configuration file") - os.Exit(1) - } - - // Initialize the worker used by the SonataFlow reconciliations to execute auxiliary async operations. - manager.InitializeSFCWorker(manager.SonataFlowControllerWorkerSize) - - if err = (&controller.SonataFlowReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Config: mgr.GetConfig(), - Recorder: mgr.GetEventRecorderFor("workflow-controller"), + if err := (&controller.LogicPlatformReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlow") + setupLog.Error(err, "unable to create controller", "controller", "LogicPlatform") os.Exit(1) } - if err = (&controller.SonataFlowBuildReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Config: mgr.GetConfig(), - Recorder: mgr.GetEventRecorderFor("build-controller"), + if err := (&controller.LogicFlowServiceReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowBuild") + setupLog.Error(err, "unable to create controller", "controller", "LogicFlowService") os.Exit(1) } - - if err = (&controller.SonataFlowPlatformReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Reader: mgr.GetAPIReader(), - Config: mgr.GetConfig(), - Recorder: mgr.GetEventRecorderFor("platform-controller"), + if err := (&controller.LogicFlowDefinitionReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowPlatform") + setupLog.Error(err, "unable to create controller", "controller", "LogicFlowDefinition") os.Exit(1) } - if err = (&controller.SonataFlowClusterPlatformReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Reader: mgr.GetAPIReader(), - Config: mgr.GetConfig(), - Recorder: mgr.GetEventRecorderFor("cluster-platform-controller"), + if err := (&controller.LogicFlowRuntimeReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowClusterPlatform") + setupLog.Error(err, "unable to create controller", "controller", "LogicFlowRuntime") os.Exit(1) } - //+kubebuilder:scaffold:builder + // +kubebuilder:scaffold:builder + + if metricsCertWatcher != nil { + setupLog.Info("Adding metrics certificate watcher to manager") + if err := mgr.Add(metricsCertWatcher); err != nil { + setupLog.Error(err, "unable to add metrics certificate watcher to manager") + os.Exit(1) + } + } - if utils.IsOpenShift() { - ocputil.MustAddToScheme(mgr.GetScheme()) + if webhookCertWatcher != nil { + setupLog.Info("Adding webhook certificate watcher to manager") + if err := mgr.Add(webhookCertWatcher); err != nil { + setupLog.Error(err, "unable to add webhook certificate watcher to manager") + os.Exit(1) + } } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { - klog.V(log.E).ErrorS(err, "unable to set up health check") + setupLog.Error(err, "unable to set up health check") os.Exit(1) } if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { - klog.V(log.E).ErrorS(err, "unable to set up ready check") + setupLog.Error(err, "unable to set up ready check") os.Exit(1) } - klog.V(log.I).InfoS("starting manager", "version:", version.GetOperatorVersion()) + setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { - klog.V(log.E).ErrorS(err, "problem running manager") + setupLog.Error(err, "problem running manager") os.Exit(1) } - } diff --git a/config/crd/bases/.gitkeep b/config/crd/bases/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/config/crd/bases/logic.kubesmarts.org_logicflowdefinitions.yaml b/config/crd/bases/logic.kubesmarts.org_logicflowdefinitions.yaml new file mode 100644 index 00000000..df22da8c --- /dev/null +++ b/config/crd/bases/logic.kubesmarts.org_logicflowdefinitions.yaml @@ -0,0 +1,55 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: logicflowdefinitions.logic.kubesmarts.org +spec: + group: logic.kubesmarts.org + names: + kind: LogicFlowDefinition + listKind: LogicFlowDefinitionList + plural: logicflowdefinitions + singular: logicflowdefinition + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LogicFlowDefinition is the Schema for the logicflowdefinitions + API. + 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: LogicFlowDefinitionSpec defines the desired state of LogicFlowDefinition. + properties: + foo: + description: Foo is an example field of LogicFlowDefinition. Edit + logicflowdefinition_types.go to remove/update + type: string + type: object + status: + description: LogicFlowDefinitionStatus defines the observed state of LogicFlowDefinition. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/logic.kubesmarts.org_logicflowruntimes.yaml b/config/crd/bases/logic.kubesmarts.org_logicflowruntimes.yaml new file mode 100644 index 00000000..e8aea9ce --- /dev/null +++ b/config/crd/bases/logic.kubesmarts.org_logicflowruntimes.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: logicflowruntimes.logic.kubesmarts.org +spec: + group: logic.kubesmarts.org + names: + kind: LogicFlowRuntime + listKind: LogicFlowRuntimeList + plural: logicflowruntimes + singular: logicflowruntime + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LogicFlowRuntime is the Schema for the logicflowruntimes API. + 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: LogicFlowRuntimeSpec defines the desired state of LogicFlowRuntime. + properties: + foo: + description: Foo is an example field of LogicFlowRuntime. Edit logicflowruntime_types.go + to remove/update + type: string + type: object + status: + description: LogicFlowRuntimeStatus defines the observed state of LogicFlowRuntime. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/logic.kubesmarts.org_logicflowservices.yaml b/config/crd/bases/logic.kubesmarts.org_logicflowservices.yaml new file mode 100644 index 00000000..99ae334f --- /dev/null +++ b/config/crd/bases/logic.kubesmarts.org_logicflowservices.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: logicflowservices.logic.kubesmarts.org +spec: + group: logic.kubesmarts.org + names: + kind: LogicFlowService + listKind: LogicFlowServiceList + plural: logicflowservices + singular: logicflowservice + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LogicFlowService is the Schema for the logicflowservices API. + 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: LogicFlowServiceSpec defines the desired state of LogicFlowService. + properties: + foo: + description: Foo is an example field of LogicFlowService. Edit logicflowservice_types.go + to remove/update + type: string + type: object + status: + description: LogicFlowServiceStatus defines the observed state of LogicFlowService. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/logic.kubesmarts.org_logicplatforms.yaml b/config/crd/bases/logic.kubesmarts.org_logicplatforms.yaml new file mode 100644 index 00000000..2b539eef --- /dev/null +++ b/config/crd/bases/logic.kubesmarts.org_logicplatforms.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: logicplatforms.logic.kubesmarts.org +spec: + group: logic.kubesmarts.org + names: + kind: LogicPlatform + listKind: LogicPlatformList + plural: logicplatforms + singular: logicplatform + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LogicPlatform is the Schema for the logicplatforms API. + 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: LogicPlatformSpec defines the desired state of LogicPlatform. + properties: + foo: + description: Foo is an example field of LogicPlatform. Edit logicplatform_types.go + to remove/update + type: string + type: object + status: + description: LogicPlatformStatus defines the observed state of LogicPlatform. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 0e5ea5df..5ca3daf0 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -1,47 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - # This kustomization.yaml is not intended to be run by itself, # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: - - bases/sonataflow.org_sonataflows.yaml - - bases/sonataflow.org_sonataflowbuilds.yaml - - bases/sonataflow.org_sonataflowplatforms.yaml - - bases/sonataflow.org_sonataflowclusterplatforms.yaml -#+kubebuilder:scaffold:crdkustomizeresource +- bases/logic.kubesmarts.org_logicplatforms.yaml +- bases/logic.kubesmarts.org_logicflowservices.yaml +- bases/logic.kubesmarts.org_logicflowdefinitions.yaml +- bases/logic.kubesmarts.org_logicflowruntimes.yaml +# +kubebuilder:scaffold:crdkustomizeresource -patchesStrategicMerge: +patches: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_workflows.yaml -#- patches/webhook_in_sonataflows.yaml -#- patches/webhook_in_sonataflowplatforms.yaml -#- patches/webhook_in_sonataflowclusterplatforms.yaml -#+kubebuilder:scaffold:crdkustomizewebhookpatch - -# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_workflows.yaml -#- patches/cainjection_in_sonataflowworkflows.yaml -#- patches/cainjection_in_sonataflowplatforms.yaml -#- patches/cainjection_in_sonataflowclusterplatforms.yaml -#+kubebuilder:scaffold:crdkustomizecainjectionpatch +# +kubebuilder:scaffold:crdkustomizewebhookpatch +# [WEBHOOK] To enable webhook, uncomment the following section # the following config is for teaching kustomize how to do kustomization for CRDs. -configurations: - - kustomizeconfig.yaml +#configurations: +#- kustomizeconfig.yaml diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml index ba9fbc51..ec5c150a 100644 --- a/config/crd/kustomizeconfig.yaml +++ b/config/crd/kustomizeconfig.yaml @@ -1,36 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - # This file is for teaching kustomize how to substitute name and namespace reference in CRD nameReference: - - kind: Service - version: v1 - fieldSpecs: - - kind: CustomResourceDefinition - version: v1 - group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/name - -namespace: +- kind: Service + version: v1 + fieldSpecs: - kind: CustomResourceDefinition version: v1 group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/namespace - create: false + path: spec/conversion/webhook/clientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false varReference: - - path: metadata/annotations +- path: metadata/annotations diff --git a/config/crd/patches/cainjection_in_sonataflowbuilds.yaml b/config/crd/patches/cainjection_in_sonataflowbuilds.yaml deleted file mode 100644 index de189658..00000000 --- a/config/crd/patches/cainjection_in_sonataflowbuilds.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sonataflowbuilds.sonataflow.org diff --git a/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml b/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml deleted file mode 100644 index 4c7092f3..00000000 --- a/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sonataflowclusterplatforms.sonataflow.org diff --git a/config/crd/patches/cainjection_in_sonataflowplatforms.yaml b/config/crd/patches/cainjection_in_sonataflowplatforms.yaml deleted file mode 100644 index 61b0f846..00000000 --- a/config/crd/patches/cainjection_in_sonataflowplatforms.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sonataflowplatforms.sonataflow.org diff --git a/config/crd/patches/cainjection_in_sonataflows.yaml b/config/crd/patches/cainjection_in_sonataflows.yaml deleted file mode 100644 index d3870e1c..00000000 --- a/config/crd/patches/cainjection_in_sonataflows.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sonataflowworkflows.sonataflow.org diff --git a/config/crd/patches/webhook_in_sonataflowbuilds.yaml b/config/crd/patches/webhook_in_sonataflowbuilds.yaml deleted file mode 100644 index f8a190fd..00000000 --- a/config/crd/patches/webhook_in_sonataflowbuilds.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: sonataflowbuilds.sonataflow.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml b/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml deleted file mode 100644 index 4cbda4bb..00000000 --- a/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: sonataflowclusterplatforms.sonataflow.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/crd/patches/webhook_in_sonataflowplatforms.yaml b/config/crd/patches/webhook_in_sonataflowplatforms.yaml deleted file mode 100644 index f805d597..00000000 --- a/config/crd/patches/webhook_in_sonataflowplatforms.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: sonataflowplatforms.sonataflow.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/crd/patches/webhook_in_sonataflows.yaml b/config/crd/patches/webhook_in_sonataflows.yaml deleted file mode 100644 index ce6cf83f..00000000 --- a/config/crd/patches/webhook_in_sonataflows.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: sonataflowworkflows.sonataflow.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/default/cert_metrics_manager_patch.yaml b/config/default/cert_metrics_manager_patch.yaml new file mode 100644 index 00000000..d9750155 --- /dev/null +++ b/config/default/cert_metrics_manager_patch.yaml @@ -0,0 +1,30 @@ +# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs. + +# Add the volumeMount for the metrics-server certs +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + mountPath: /tmp/k8s-metrics-server/metrics-certs + name: metrics-certs + readOnly: true + +# Add the --metrics-cert-path argument for the metrics server +- op: add + path: /spec/template/spec/containers/0/args/- + value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs + +# Add the metrics-server certs volume configuration +- op: add + path: /spec/template/spec/volumes/- + value: + name: metrics-certs + secret: + secretName: metrics-server-cert + optional: false + items: + - key: ca.crt + path: ca.crt + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key diff --git a/config/default/controllers_config_patch.yaml b/config/default/controllers_config_patch.yaml deleted file mode 100644 index 00a2b5c2..00000000 --- a/config/default/controllers_config_patch.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - volumeMounts: - - name: controllers-config - mountPath: /config/controllers_cfg.yaml - subPath: controllers_cfg.yaml - volumes: - - name: controllers-config - configMap: - name: controllers-config diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 13814908..e95abe8b 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,39 +1,23 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Labels to add to all resources and selectors. -# https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels -commonLabels: - app.kubernetes.io/name: sonataflow-operator - # Adds namespace to all resources. -namespace: sonataflow-operator-system +namespace: logic-operator-system # Value of this field is prepended to the # names of all resources, e.g. a deployment named # "wordpress" becomes "alices-wordpress". # Note that it should also match with the prefix (text before '-') of the namespace # field above. -namePrefix: sonataflow-operator- +namePrefix: logic-operator- # Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue +#labels: +#- includeSelectors: true +# pairs: +# someName: someValue +resources: +- ../crd +- ../rbac +- ../manager # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml #- ../webhook @@ -41,33 +25,210 @@ namePrefix: sonataflow-operator- #- ../certmanager # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus +# [METRICS] Expose the controller manager metrics service. +- metrics_service.yaml +# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy. +# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics. +# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will +# be able to communicate with the Webhook Server. +#- ../network-policy -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -#- manager_config_patch.yaml +# Uncomment the patches line if you enable Metrics +patches: +# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443. +# More info: https://book.kubebuilder.io/reference/metrics +- path: manager_metrics_patch.yaml + target: + kind: Deployment -# Mount the custom controllers config +# Uncomment the patches line if you enable Metrics and CertManager +# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line. +# This patch will protect the metrics with certManager self-signed certs. +#- path: cert_metrics_manager_patch.yaml +# target: +# kind: Deployment # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- manager_webhook_patch.yaml +#- path: manager_webhook_patch.yaml +# target: +# kind: Deployment -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - ../crd - - ../rbac - - ../manager -patches: - - path: manager_auth_proxy_patch.yaml - - path: controllers_config_patch.yaml +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +# Uncomment the following replacements to add the cert-manager CA injection annotations +#replacements: +# - source: # Uncomment the following block to enable certificates for metrics +# kind: Service +# version: v1 +# name: controller-manager-metrics-service +# fieldPath: metadata.name +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: metrics-certs +# fieldPaths: +# - spec.dnsNames.0 +# - spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 0 +# create: true +# - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor +# kind: ServiceMonitor +# group: monitoring.coreos.com +# version: v1 +# name: controller-manager-metrics-monitor +# fieldPaths: +# - spec.endpoints.0.tlsConfig.serverName +# options: +# delimiter: '.' +# index: 0 +# create: true +# +# - source: +# kind: Service +# version: v1 +# name: controller-manager-metrics-service +# fieldPath: metadata.namespace +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: metrics-certs +# fieldPaths: +# - spec.dnsNames.0 +# - spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 1 +# create: true +# - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor +# kind: ServiceMonitor +# group: monitoring.coreos.com +# version: v1 +# name: controller-manager-metrics-monitor +# fieldPaths: +# - spec.endpoints.0.tlsConfig.serverName +# options: +# delimiter: '.' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have any webhook +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.name # Name of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 0 +# create: true +# - source: +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.namespace # Namespace of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # This name should match the one in certificate.yaml +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting ) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD. +# +kubebuilder:scaffold:crdkustomizecainjectionns +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD. +# +kubebuilder:scaffold:crdkustomizecainjectionname diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml deleted file mode 100644 index 43eab6fe..00000000 --- a/config/default/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: kube-rbac-proxy - image: quay.io/brancz/kube-rbac-proxy:v0.13.1 - env: - - name: RELATED_IMAGE_KUBE_RBAC_PROXY - value: quay.io/brancz/kube-rbac-proxy:v0.13.1 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=0" - ports: - - containerPort: 8443 - protocol: TCP - name: https - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - seccompProfile: - type: RuntimeDefault - capabilities: - drop: - - ALL - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" - - "--lease-duration=60s" - - "--renew-deadline=40s" - - "--retry-period=15s" - - "--qps=50" - - "--burst=100" - - "--v=0" diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml deleted file mode 100644 index 24904fa0..00000000 --- a/config/default/manager_config_patch.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config diff --git a/config/default/manager_metrics_patch.yaml b/config/default/manager_metrics_patch.yaml new file mode 100644 index 00000000..2aaef653 --- /dev/null +++ b/config/default/manager_metrics_patch.yaml @@ -0,0 +1,4 @@ +# This patch adds the args to allow exposing the metrics endpoint using HTTPS +- op: add + path: /spec/template/spec/containers/0/args/0 + value: --metrics-bind-address=:8443 diff --git a/config/default/metrics_service.yaml b/config/default/metrics_service.yaml new file mode 100644 index 00000000..6c8de55b --- /dev/null +++ b/config/default/metrics_service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: 8443 + selector: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator diff --git a/config/manager/SonataFlow-Builder.containerfile b/config/manager/SonataFlow-Builder.containerfile deleted file mode 100644 index 3cd05caf..00000000 --- a/config/manager/SonataFlow-Builder.containerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -FROM docker.io/apache/incubator-kie-sonataflow-builder:main AS builder - -# variables that can be overridden by the builder -# To add a Quarkus extension to your application -ARG QUARKUS_EXTENSIONS -# Args to pass to the Quarkus CLI add extension command -ARG QUARKUS_ADD_EXTENSION_ARGS -# Additional java/mvn arguments to pass to the builder -ARG MAVEN_ARGS_APPEND - -# Copy from build context to skeleton resources project -COPY --chown=1001 . ./resources - -RUN /home/kogito/launch/build-app.sh ./resources - -#============================= -# Runtime Run -#============================= -FROM registry.access.redhat.com/ubi9/openjdk-17-runtime:latest - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/lib/ /deployments/lib/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/*.jar /deployments/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/app/ /deployments/app/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 185 -ENV AB_JOLOKIA_OFF="" -ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml deleted file mode 100644 index e980554b..00000000 --- a/config/manager/controller_manager_config.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: 1be5e57d.kiegroup.org diff --git a/config/manager/controllers_cfg.yaml b/config/manager/controllers_cfg.yaml deleted file mode 100644 index cc717ee5..00000000 --- a/config/manager/controllers_cfg.yaml +++ /dev/null @@ -1,64 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The default size of Kaniko PVC when using the internal operator builder manager -defaultPvcKanikoSize: 1Gi -# How much time (in seconds) to wait for a devmode workflow to start. -# This information is used for the controller manager to create new devmode containers and setup the healthcheck probes. -healthFailureThresholdDevMode: 50 -# Default image used internally by the Operator Managed Kaniko builder to create the warmup pods -kanikoDefaultWarmerImageTag: gcr.io/kaniko-project/warmer:v1.9.0 -# Default image used internally by the Operator Managed Kaniko builder to create the executor pods -kanikoExecutorImageTag: gcr.io/kaniko-project/executor:v1.9.0 -# The Jobs Service image to use, if empty the operator will use the default Apache Community one based on the current operator's version -jobsServicePostgreSQLImageTag: "" -jobsServiceEphemeralImageTag: "" -# The Data Index image to use, if empty the operator will use the default Apache Community one based on the current operator's version -dataIndexPostgreSQLImageTag: "" -dataIndexEphemeralImageTag: "" -# The Kogito PostgreSQL DB Migrator image to use -dbMigratorToolImageTag: "" -# SonataFlow base builder image used in the internal Dockerfile to build workflow applications in preview profile -# Order of precedence is: -# 1. SonataFlowPlatform in the given namespace -# 2. This configuration -# 3. The FROM in the Dockerfile in the operator's namespace "sonataflow-operator-builder-config" configMap. -# If 1 or 2, the FROM tag will be replaced by the tag there. -# If empty the operator will use the default Apache Community one based on the current operator's version. -sonataFlowBaseBuilderImageTag: "" -# The image to use to deploy SonataFlow workflow images in devmode profile. -# If empty the operator will use the default Apache Community one based on the current operator's version. -sonataFlowDevModeImageTag: "" -# The default name of the builder configMap in the operator's namespace -builderConfigMapName: "sonataflow-operator-builder-config" -# Quarkus extensions required for workflows persistence. These extensions are used by the SonataFlow build system, -# in cases where the workflow being built has configured postgresql persistence. -postgreSQLPersistenceExtensions: - - groupId: io.quarkus - artifactId: quarkus-jdbc-postgresql - - groupId: io.quarkus - artifactId: quarkus-agroal - - groupId: org.kie - artifactId: kie-addons-quarkus-persistence-jdbc -# If true, the workflow deployments will be configured to send accumulated workflow status change events to the Data -# Index Service reducing the number of produced events. Set to false to send individual events. -kogitoEventsGrouping: true -# If true, the accumulated workflow status change events will be sent in binary mode. (reduces the evens size) -kogitoEventsGroupingBinary: true -# If true, the accumulated workflow status change events, when sent in binary mode, will be gzipped at the cost of -# some performance. -kogitoEventsGroupingCompress: false diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index ecf298bf..5c5f0b84 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,51 +1,2 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - resources: - manager.yaml -generatorOptions: - disableNameSuffixHash: true -# No need to generate this CM since we are not using it. -# Must also uncomment config/manager/kustomization.yaml to mount it in the controller - -#- files: -# - controller_manager_config.yaml -# name: manager-config -configMapGenerator: -- files: - - Dockerfile=SonataFlow-Builder.containerfile - literals: - - DEFAULT_WORKFLOW_EXTENSION=.sw.json - name: builder-config -- files: - - controllers_cfg.yaml - name: controllers-config -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - # Changed during "make build", do not attempt to modify it manually! -images: -- name: controller - newName: quay.io/kubesmarts/logic-operator - newTag: 2.0.0 -# Patching the manager deployment file to add an env var with the operator namespace in -patches: -- path: manager_env_patch.yaml - target: - kind: Deployment - name: controller-manager - namespace: system - version: v1 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 59d67147..e16f672b 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -1,23 +1,10 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - apiVersion: v1 kind: Namespace metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: system --- apiVersion: apps/v1 @@ -25,52 +12,87 @@ kind: Deployment metadata: name: controller-manager namespace: system + labels: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize spec: selector: matchLabels: - app.kubernetes.io/name: sonataflow-operator + control-plane: controller-manager + app.kubernetes.io/name: logic-operator replicas: 1 template: metadata: annotations: kubectl.kubernetes.io/default-container: manager labels: - app.kubernetes.io/name: sonataflow-operator + control-plane: controller-manager + app.kubernetes.io/name: logic-operator spec: + # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # according to the platforms which are supported by your solution. + # It is considered best practice to support multiple architectures. You can + # build your manager image using the makefile target docker-buildx. + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/arch + # operator: In + # values: + # - amd64 + # - arm64 + # - ppc64le + # - s390x + # - key: kubernetes.io/os + # operator: In + # values: + # - linux securityContext: + # Projects are configured by default to adhere to the "restricted" Pod Security Standards. + # This ensures that deployments meet the highest security requirements for Kubernetes. + # For more details, see: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - - command: - - /usr/local/bin/manager - args: - - --leader-elect - - --v=2 - image: controller:latest - name: manager - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - resources: - limits: - cpu: 500m - memory: 500Mi - requests: - cpu: 100m - memory: 200Mi + - command: + - /manager + args: + - --leader-elect + - --health-probe-bind-address=:8081 + image: controller:latest + name: manager + ports: [] + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + # TODO(user): Configure the resources accordingly based on the project requirements. + # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + volumeMounts: [] + volumes: [] serviceAccountName: controller-manager terminationGracePeriodSeconds: 10 diff --git a/config/manager/manager_env_patch.yaml b/config/manager/manager_env_patch.yaml deleted file mode 100644 index cd62256e..00000000 --- a/config/manager/manager_env_patch.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager -spec: - template: - spec: - containers: - - name: manager - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL - value: docker.io/apache/incubator-kie-kogito-jobs-service-postgresql:main - - name: RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL - value: docker.io/apache/incubator-kie-kogito-jobs-service-ephemeral:main - - name: RELATED_IMAGE_DATA_INDEX_POSTGRESQL - value: docker.io/apache/incubator-kie-kogito-data-index-postgresql:main - - name: RELATED_IMAGE_DATA_INDEX_EPHEMERAL - value: docker.io/apache/incubator-kie-kogito-data-index-ephemeral:main - - name: RELATED_IMAGE_DB_MIGRATOR_TOOL - value: docker.io/apache/kie-kogito-db-migrator-tool:main - - name: RELATED_IMAGE_BASE_BUILDER - value: docker.io/apache/incubator-kie-sonataflow-builder:main - - name: RELATED_IMAGE_DEVMODE - value: docker.io/apache/incubator-kie-sonataflow-devmode:main diff --git a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml b/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml deleted file mode 100644 index 232f23cc..00000000 --- a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml +++ /dev/null @@ -1,303 +0,0 @@ -# Copyright 2026 The Kubesmarts 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. - -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: '[]' - capabilities: Basic Install - categories: Application Runtime - containerImage: docker.io/apache/incubator-kie-sonataflow-operator:main - description: SonataFlow Kubernetes Operator for deploying workflow applications - based on the CNCF Serverless Workflow specification - operators.operatorframework.io/internal-objects: '["sonataflowbuilds.sonataflow.org"]' - repository: https://github.com/apache/incubator-kie-tools/packages/sonataflow-operator - support: Apache KIE - name: sonataflow-operator.v0.0.0 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: SonataFlowBuild is an internal custom resource to control workflow - build instances in the target platform - displayName: SonataFlowBuild - kind: SonataFlowBuild - name: sonataflowbuilds.sonataflow.org - resources: - - kind: BuildConfig - name: An Openshift Build Config - version: build.openshift.io/v1 - specDescriptors: - - description: 'Arguments lists the command line arguments to send to the internal - builder command. Depending on the build method you might set this attribute - instead of BuildArgs. For example: ".spec.arguments=verbose=3". Please see - the SonataFlow guides.' - displayName: Arguments - path: arguments - - description: Optional build arguments that can be set to the internal build - (e.g. Docker ARG) - displayName: BuildArgs - path: buildArgs - - description: Optional environment variables to add to the internal build - displayName: Envs - path: envs - - description: Resources optional compute resource requirements for the builder - displayName: Resources - path: resources - - description: Timeout defines the Build maximum execution duration. The Build - deadline is set to the Build start time plus the Timeout duration. If the - Build deadline is exceeded, the Build context is canceled, and its phase - set to BuildPhaseFailed. - displayName: Timeout - path: timeout - statusDescriptors: - - description: BuildPhase Current phase of the build - displayName: BuildPhase - path: buildPhase - - description: Error Last error found during build - displayName: Error - path: error - - description: ImageTag The final image tag produced by this build instance - displayName: ImageTag - path: imageTag - - description: InnerBuild is a reference to an internal build object, which - can be anything known only to internal builders. - displayName: InnerBuild - path: innerBuild - version: v1alpha08 - - description: SonataFlowClusterPlatform is the Schema for the sonataflowclusterplatforms - API - displayName: SonataFlowClusterPlatform - kind: SonataFlowClusterPlatform - name: sonataflowclusterplatforms.sonataflow.org - resources: - - kind: SonataFlowPlatform - name: A SonataFlow Platform - version: sonataflow.org/v1alpha08 - specDescriptors: - - description: Capabilities defines which platform capabilities should be applied - cluster-wide. If nil, defaults to `capabilities.workflows["services"]` - displayName: Capabilities - path: capabilities - - description: PlatformRef defines which existing SonataFlowPlatform's supporting - services should be used cluster-wide. - displayName: PlatformRef - path: platformRef - - description: Name of the SonataFlowPlatform - displayName: Platform_Name - path: platformRef.name - - description: Namespace of the SonataFlowPlatform - displayName: Platform_NS - path: platformRef.namespace - statusDescriptors: - - description: Version the operator version controlling this ClusterPlatform - displayName: version - path: version - version: v1alpha08 - - description: SonataFlowPlatform is the descriptor for the workflow platform - infrastructure. - displayName: SonataFlowPlatform - kind: SonataFlowPlatform - name: sonataflowplatforms.sonataflow.org - resources: - - kind: Namespace - name: The Namespace controlled by the platform - version: v1 - specDescriptors: - - description: Build Attributes for building workflows in the target platform - displayName: Build - path: build - - description: 'Arguments lists the command line arguments to send to the internal - builder command. Depending on the build method you might set this attribute - instead of BuildArgs. For example: ".spec.arguments=verbose=3". Please see - the SonataFlow guides.' - displayName: Arguments - path: build.template.arguments - - description: Optional build arguments that can be set to the internal build - (e.g. Docker ARG) - displayName: BuildArgs - path: build.template.buildArgs - - description: Optional environment variables to add to the internal build - displayName: Envs - path: build.template.envs - - description: Resources optional compute resource requirements for the builder - displayName: Resources - path: build.template.resources - - description: Timeout defines the Build maximum execution duration. The Build - deadline is set to the Build start time plus the Timeout duration. If the - Build deadline is exceeded, the Build context is canceled, and its phase - set to BuildPhaseFailed. - displayName: Timeout - path: build.template.timeout - - description: DevMode Attributes for running workflows in devmode (immutable, - no build required) - displayName: DevMode - path: devMode - - description: Broker to communicate with workflow deployment. It can be the - default broker when the workflow, Dataindex, or Jobservice does not have - a sink or source specified. - displayName: broker - path: eventing.broker - - description: 'Services attributes for deploying supporting applications like - Data Index & Job Service. Only workflows without the `sonataflow.org/profile: - dev` annotation will be configured to use these service(s). Setting this - will override the use of any cluster-scoped services that might be defined - via `SonataFlowClusterPlatform`.' - displayName: Services - path: services - - description: PodTemplate describes the deployment details of this platform - service instance. - displayName: podTemplate - path: services.dataIndex.podTemplate - - description: PodTemplate describes the deployment details of this platform - service instance. - displayName: podTemplate - path: services.jobService.podTemplate - statusDescriptors: - - description: Cluster what kind of cluster you're running (ie, plain Kubernetes - or OpenShift) - displayName: cluster - path: cluster - - description: ClusterPlatformRef information related to the (optional) active - SonataFlowClusterPlatform - displayName: clusterPlatformRef - path: clusterPlatformRef - - description: Info generic information related to the Platform - displayName: info - path: info - - displayName: dbMigrationStatus - path: sonataFlowPlatformDBMigrationPhase - - description: Triggers list of triggers created for the SonataFlowPlatform - displayName: triggers - path: triggers - - description: Version the operator version controlling this Platform - displayName: version - path: version - version: v1alpha08 - - description: SonataFlow is the descriptor representation for a workflow application - based on the CNCF Serverless Workflow specification. - displayName: SonataFlow - kind: SonataFlow - name: sonataflows.sonataflow.org - resources: - - kind: Deployment - name: A Deployment for the Flow - version: apps/v1 - - kind: Service - name: A Knative Serving Service for the Flow - version: serving.knative.dev/v1 - - kind: Service - name: A Service for the Flow - version: v1 - - kind: SonataFlowBuild - name: A SonataFlow Build - version: sonataflow.org/v1alpha08 - - kind: Route - name: An OpenShift Route for the Flow - version: route.openshift.io/v1 - - kind: ConfigMap - name: The ConfigMaps with Flow definition and additional configuration files - version: v1 - specDescriptors: - - description: Flow the workflow definition. - displayName: flow - path: flow - - description: PodTemplate describes the deployment details of this SonataFlow - instance. - displayName: podTemplate - path: podTemplate - - description: Resources workflow resources that are linked to this workflow - definition. For example, a collection of OpenAPI specification files. - displayName: resources - path: resources - - description: Sink describes the sinkBinding details of this SonataFlow instance. - displayName: sink - path: sink - - description: Sources describes the list of sources used to create triggers - for events consumed by this SonataFlow instance. - displayName: sources - path: sources - statusDescriptors: - - description: Address is used as a part of Addressable interface (status.address.url) - for knative - displayName: address - path: address - - description: Endpoint is an externally accessible URL of the workflow - displayName: endpoint - path: endpoint - - displayName: finalizerAttempts - path: finalizerAttempts - - displayName: finalizerSucceed - path: finalizerSucceed - - displayName: flowRevision - path: flowCRC - - displayName: lastTimeFinalizerAttempt - path: lastTimeFinalizerAttempt - - displayName: lastTimeRecoverAttempt - path: lastTimeRecoverAttempt - - displayName: lastTimeStatusNotified - path: lastTimeStatusNotified - - description: Platform displays which platform is being used by this workflow - displayName: platform - path: platform - - description: keeps track of how many failure recovers a given workflow had - so far - displayName: recoverFailureAttempts - path: recoverFailureAttempts - - description: Services displays which platform services are being used by this - workflow - displayName: services - path: services - - description: Triggers list of triggers created for the SonataFlow - displayName: triggers - path: triggers - version: v1alpha08 - description: |- - SonataFlow Kubernetes Operator for deploying workflow applications - based on the [CNCF Serverless Workflow specification](https://serverlessworkflow.io/): - - * Deploy workflow applications using the [dev profile](https://sonataflow.org/serverlessworkflow/latest/cloud/operator/developing-workflows.html), suited for the your development cycle - * Build workflow applications based on the platform you're currently working on. - displayName: SonataFlow Operator - install: - spec: - deployments: null - strategy: "" - installModes: - - supported: false - type: OwnNamespace - - supported: false - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - sonataflow - - cncf - - serverless - - serverlessworkflow - links: - - name: Product Page - url: https://sonataflow.org/serverlessworkflow/latest/index.html - maintainers: - - email: dev@kie.apache.org - name: Apache KIE - maturity: stable - minKubeVersion: 1.23.0 - provider: - name: Apache KIE - version: 0.0.0 diff --git a/config/manifests/kustomization.yaml b/config/manifests/kustomization.yaml index e5af175b..46f1e62c 100644 --- a/config/manifests/kustomization.yaml +++ b/config/manifests/kustomization.yaml @@ -1,27 +1,11 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - # These resources constitute the fully configured set of manifests # used to generate the 'manifests/' directory in a bundle. resources: - - bases/sonataflow-operator.clusterserviceversion.yaml - - ../default - - ../samples - - ../scorecard +- bases/logic-operator.clusterserviceversion.yaml +- ../default +- ../samples +- ../scorecard + # [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix. # Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager. # These patches remove the unnecessary "cert" volume and its manager container volumeMount. @@ -36,7 +20,8 @@ resources: # # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs. # # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment. # - op: remove -# path: /spec/template/spec/containers/1/volumeMounts/0 + +# path: /spec/template/spec/containers/0/volumeMounts/0 # # Remove the "cert" volume, since OLM will create and mount a set of certs. # # Update the indices in this path if adding or removing volumes in the manager's Deployment. # - op: remove diff --git a/config/network-policy/allow-metrics-traffic.yaml b/config/network-policy/allow-metrics-traffic.yaml new file mode 100644 index 00000000..b484231f --- /dev/null +++ b/config/network-policy/allow-metrics-traffic.yaml @@ -0,0 +1,27 @@ +# This NetworkPolicy allows ingress traffic +# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those +# namespaces are able to gather data from the metrics endpoint. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: allow-metrics-traffic + namespace: system +spec: + podSelector: + matchLabels: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator + policyTypes: + - Ingress + ingress: + # This allows ingress traffic from any namespace with the label metrics: enabled + - from: + - namespaceSelector: + matchLabels: + metrics: enabled # Only from namespaces with this label + ports: + - port: 8443 + protocol: TCP diff --git a/config/network-policy/kustomization.yaml b/config/network-policy/kustomization.yaml new file mode 100644 index 00000000..ec0fb5e5 --- /dev/null +++ b/config/network-policy/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- allow-metrics-traffic.yaml diff --git a/config/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml index 580badef..fdc5481b 100644 --- a/config/prometheus/kustomization.yaml +++ b/config/prometheus/kustomization.yaml @@ -1,19 +1,11 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - resources: - - monitor.yaml +- monitor.yaml + +# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus +# to securely reference certificates created and managed by cert-manager. +# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml +# to mount the "metrics-server-cert" secret in the Manager Deployment. +#patches: +# - path: monitor_tls_patch.yaml +# target: +# kind: ServiceMonitor diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index ba967ed5..7904b1b5 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -1,34 +1,27 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - # Prometheus Monitor Service (Metrics) apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-monitor namespace: system spec: endpoints: - path: /metrics - port: https + port: https # Ensure this is the name of the port that exposes HTTPS metrics scheme: https bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token tlsConfig: + # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables + # certificate verification, exposing the system to potential man-in-the-middle attacks. + # For production environments, it is recommended to use cert-manager for automatic TLS certificate management. + # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml, + # which securely references the certificate from the 'metrics-server-cert' secret. insecureSkipVerify: true selector: matchLabels: - app.kubernetes.io/name: sonataflow-operator + control-plane: controller-manager + app.kubernetes.io/name: logic-operator diff --git a/config/prometheus/monitor_tls_patch.yaml b/config/prometheus/monitor_tls_patch.yaml new file mode 100644 index 00000000..5bf84ce0 --- /dev/null +++ b/config/prometheus/monitor_tls_patch.yaml @@ -0,0 +1,19 @@ +# Patch for Prometheus ServiceMonitor to enable secure TLS configuration +# using certificates managed by cert-manager +- op: replace + path: /spec/endpoints/0/tlsConfig + value: + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize + serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc + insecureSkipVerify: false + ca: + secret: + name: metrics-server-cert + key: ca.crt + cert: + secret: + name: metrics-server-cert + key: tls.crt + keySecret: + name: metrics-server-cert + key: tls.key diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml deleted file mode 100644 index d9e12e6a..00000000 --- a/config/rbac/auth_proxy_client_clusterrole.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: metrics-reader -rules: - - nonResourceURLs: - - "/metrics" - verbs: - - get diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml deleted file mode 100644 index 42f1a18c..00000000 --- a/config/rbac/auth_proxy_role.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: proxy-role -rules: - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml deleted file mode 100644 index 1d170e0a..00000000 --- a/config/rbac/auth_proxy_role_binding.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: proxy-role -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml deleted file mode 100644 index b6a3898a..00000000 --- a/config/rbac/auth_proxy_service.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: v1 -kind: Service -metadata: - name: controller-manager-metrics-service - namespace: system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https - selector: - app.kubernetes.io/name: sonataflow-operator diff --git a/config/rbac/builder_role.yaml b/config/rbac/builder_role.yaml deleted file mode 100644 index 128a3735..00000000 --- a/config/rbac/builder_role.yaml +++ /dev/null @@ -1,85 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: builder-manager-role -rules: - - apiGroups: - - "" - resources: - - configmaps - - pods - - pods/exec - - services - - services/finalizers - - namespaces - - serviceaccounts - - persistentvolumeclaims - - secrets - - events - - deployments - - nodes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - apps - resources: - - configmaps - - pods - - pods/exec - - services - - services/finalizers - - namespaces - - serviceaccounts - - persistentvolumeclaims - - secrets - - events - - deployments - - nodes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - rolebindings - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch diff --git a/config/rbac/builder_role_binding.yaml b/config/rbac/builder_role_binding.yaml deleted file mode 100644 index d67f0998..00000000 --- a/config/rbac/builder_role_binding.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: builder-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: builder-manager-role -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/knative_role.yaml b/config/rbac/knative_role.yaml deleted file mode 100644 index a7c3beed..00000000 --- a/config/rbac/knative_role.yaml +++ /dev/null @@ -1,69 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: knative-manager-role -rules: - - apiGroups: - - eventing.knative.dev - resources: - - triggers - - triggers/status - - triggers/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - sources.knative.dev - resources: - - sinkbindings - - sinkbindings/status - - sinkbindings/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - serving.knative.dev - resources: - - service - - services - - services/status - - services/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch diff --git a/config/rbac/knative_role_binding.yaml b/config/rbac/knative_role_binding.yaml deleted file mode 100644 index ba0b4e3e..00000000 --- a/config/rbac/knative_role_binding.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: knative-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: knative-manager-role -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 53be7b1f..134bcfde 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -1,45 +1,37 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - resources: - # All RBAC will be applied under this service account in - # the deployment namespace. You may comment out this resource - # if your manager will use a service account that exists at - # runtime. Be sure to update RoleBinding and ClusterRoleBinding - # subjects if changing service account names. - - service_account.yaml - - role.yaml - - role_binding.yaml - - builder_role.yaml - - builder_role_binding.yaml - - leader_election_role.yaml - - leader_election_role_binding.yaml - - openshift_role.yaml - - openshift_role_binding.yaml - - operator_role_leases.yaml - - operator_role_binding_leases.yaml - - service_discovery_role.yaml - - service_discovery_role_binding.yaml - - knative_role.yaml - - knative_role_binding.yaml - # Comment the following 4 lines if you want to disable - # the auth proxy (https://github.com/brancz/kube-rbac-proxy) - # which protects your /metrics endpoint. - - auth_proxy_service.yaml - - auth_proxy_role.yaml - - auth_proxy_role_binding.yaml - - auth_proxy_client_clusterrole.yaml +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# The following RBAC configurations are used to protect +# the metrics endpoint with authn/authz. These configurations +# ensure that only authorized users and service accounts +# can access the metrics endpoint. Comment the following +# permissions if you want to disable this protection. +# More info: https://book.kubebuilder.io/reference/metrics.html +- metrics_auth_role.yaml +- metrics_auth_role_binding.yaml +- metrics_reader_role.yaml +# For each CRD, "Admin", "Editor" and "Viewer" roles are scaffolded by +# default, aiding admins in cluster management. Those roles are +# not used by the logic-operator itself. You can comment the following lines +# if you do not want those helpers be installed with your Project. +- logicflowruntime_admin_role.yaml +- logicflowruntime_editor_role.yaml +- logicflowruntime_viewer_role.yaml +- logicflowdefinition_admin_role.yaml +- logicflowdefinition_editor_role.yaml +- logicflowdefinition_viewer_role.yaml +- logicflowservice_admin_role.yaml +- logicflowservice_editor_role.yaml +- logicflowservice_viewer_role.yaml +- logicplatform_admin_role.yaml +- logicplatform_editor_role.yaml +- logicplatform_viewer_role.yaml + diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml index 8b0d6799..b5e37445 100644 --- a/config/rbac/leader_election_role.yaml +++ b/config/rbac/leader_election_role.yaml @@ -1,54 +1,40 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - # permissions to do leader election. apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: leader-election-role rules: - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml index 9131cd73..5a83de9f 100644 --- a/config/rbac/leader_election_role_binding.yaml +++ b/config/rbac/leader_election_role_binding.yaml @@ -1,29 +1,15 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: leader-election-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: leader-election-role subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/logicflowdefinition_admin_role.yaml b/config/rbac/logicflowdefinition_admin_role.yaml new file mode 100644 index 00000000..de58c1b4 --- /dev/null +++ b/config/rbac/logicflowdefinition_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over logic.kubesmarts.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowdefinition-admin-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions + verbs: + - '*' +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions/status + verbs: + - get diff --git a/config/rbac/logicflowdefinition_editor_role.yaml b/config/rbac/logicflowdefinition_editor_role.yaml new file mode 100644 index 00000000..9b5272d7 --- /dev/null +++ b/config/rbac/logicflowdefinition_editor_role.yaml @@ -0,0 +1,33 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the logic.kubesmarts.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowdefinition-editor-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions/status + verbs: + - get diff --git a/config/rbac/logicflowdefinition_viewer_role.yaml b/config/rbac/logicflowdefinition_viewer_role.yaml new file mode 100644 index 00000000..6b3b7c42 --- /dev/null +++ b/config/rbac/logicflowdefinition_viewer_role.yaml @@ -0,0 +1,29 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to logic.kubesmarts.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowdefinition-viewer-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions + verbs: + - get + - list + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowdefinitions/status + verbs: + - get diff --git a/config/rbac/logicflowruntime_admin_role.yaml b/config/rbac/logicflowruntime_admin_role.yaml new file mode 100644 index 00000000..0a26cf92 --- /dev/null +++ b/config/rbac/logicflowruntime_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over logic.kubesmarts.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowruntime-admin-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes + verbs: + - '*' +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes/status + verbs: + - get diff --git a/config/rbac/logicflowruntime_editor_role.yaml b/config/rbac/logicflowruntime_editor_role.yaml new file mode 100644 index 00000000..1743a192 --- /dev/null +++ b/config/rbac/logicflowruntime_editor_role.yaml @@ -0,0 +1,33 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the logic.kubesmarts.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowruntime-editor-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes/status + verbs: + - get diff --git a/config/rbac/logicflowruntime_viewer_role.yaml b/config/rbac/logicflowruntime_viewer_role.yaml new file mode 100644 index 00000000..5a10774c --- /dev/null +++ b/config/rbac/logicflowruntime_viewer_role.yaml @@ -0,0 +1,29 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to logic.kubesmarts.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowruntime-viewer-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes + verbs: + - get + - list + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowruntimes/status + verbs: + - get diff --git a/config/rbac/logicflowservice_admin_role.yaml b/config/rbac/logicflowservice_admin_role.yaml new file mode 100644 index 00000000..37cf368f --- /dev/null +++ b/config/rbac/logicflowservice_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over logic.kubesmarts.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowservice-admin-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices + verbs: + - '*' +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices/status + verbs: + - get diff --git a/config/rbac/logicflowservice_editor_role.yaml b/config/rbac/logicflowservice_editor_role.yaml new file mode 100644 index 00000000..075fbddc --- /dev/null +++ b/config/rbac/logicflowservice_editor_role.yaml @@ -0,0 +1,33 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the logic.kubesmarts.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowservice-editor-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices/status + verbs: + - get diff --git a/config/rbac/logicflowservice_viewer_role.yaml b/config/rbac/logicflowservice_viewer_role.yaml new file mode 100644 index 00000000..0f30267f --- /dev/null +++ b/config/rbac/logicflowservice_viewer_role.yaml @@ -0,0 +1,29 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to logic.kubesmarts.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowservice-viewer-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices + verbs: + - get + - list + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicflowservices/status + verbs: + - get diff --git a/config/rbac/logicplatform_admin_role.yaml b/config/rbac/logicplatform_admin_role.yaml new file mode 100644 index 00000000..4af3686a --- /dev/null +++ b/config/rbac/logicplatform_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over logic.kubesmarts.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicplatform-admin-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms + verbs: + - '*' +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms/status + verbs: + - get diff --git a/config/rbac/logicplatform_editor_role.yaml b/config/rbac/logicplatform_editor_role.yaml new file mode 100644 index 00000000..3b264aa0 --- /dev/null +++ b/config/rbac/logicplatform_editor_role.yaml @@ -0,0 +1,33 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the logic.kubesmarts.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicplatform-editor-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms/status + verbs: + - get diff --git a/config/rbac/logicplatform_viewer_role.yaml b/config/rbac/logicplatform_viewer_role.yaml new file mode 100644 index 00000000..3b03140e --- /dev/null +++ b/config/rbac/logicplatform_viewer_role.yaml @@ -0,0 +1,29 @@ +# This rule is not used by the project logic-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to logic.kubesmarts.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicplatform-viewer-role +rules: +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms + verbs: + - get + - list + - watch +- apiGroups: + - logic.kubesmarts.org + resources: + - logicplatforms/status + verbs: + - get diff --git a/config/rbac/metrics_auth_role.yaml b/config/rbac/metrics_auth_role.yaml new file mode 100644 index 00000000..32d2e4ec --- /dev/null +++ b/config/rbac/metrics_auth_role.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-auth-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/config/rbac/metrics_auth_role_binding.yaml b/config/rbac/metrics_auth_role_binding.yaml new file mode 100644 index 00000000..e775d67f --- /dev/null +++ b/config/rbac/metrics_auth_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: metrics-auth-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: metrics-auth-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/metrics_reader_role.yaml b/config/rbac/metrics_reader_role.yaml new file mode 100644 index 00000000..51a75db4 --- /dev/null +++ b/config/rbac/metrics_reader_role.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/config/rbac/openshift_role.yaml b/config/rbac/openshift_role.yaml deleted file mode 100644 index a436fcd3..00000000 --- a/config/rbac/openshift_role.yaml +++ /dev/null @@ -1,113 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: openshift-manager-role -rules: - - apiGroups: - - route.openshift.io - resources: - - route - - routes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - route.openshift.io - resources: - - route/finalizers - - routes/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch - - apiGroups: - - image.openshift.io - resources: - - imagestreams - - imagestreamtags - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - image.openshift.io - resources: - - imagestreams/finalizers - - imagestreamtags/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch - - apiGroups: - - build.openshift.io - resources: - - buildconfigs - - builds - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - build.openshift.io - resources: - - buildconfigs/finalizers - - builds/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch - - apiGroups: - - build.openshift.io - resources: - - buildconfigs/instantiatebinary - verbs: - - create diff --git a/config/rbac/openshift_role_binding.yaml b/config/rbac/openshift_role_binding.yaml deleted file mode 100644 index 628b9673..00000000 --- a/config/rbac/openshift_role_binding.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: openshift-manager-role -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/operator_role_binding_leases.yaml b/config/rbac/operator_role_binding_leases.yaml deleted file mode 100644 index f258ef7d..00000000 --- a/config/rbac/operator_role_binding_leases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: leases-binding -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system -roleRef: - kind: ClusterRole - name: leases - apiGroup: rbac.authorization.k8s.io diff --git a/config/rbac/operator_role_leases.yaml b/config/rbac/operator_role_leases.yaml deleted file mode 100644 index 23d4f6a6..00000000 --- a/config/rbac/operator_role_leases.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: leases -rules: - - apiGroups: - - "coordination.k8s.io" - resources: - - leases - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 10239a0b..8488e305 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,17 +1,3 @@ -# Copyright 2026 The Kubesmarts 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. - --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -19,63 +5,12 @@ metadata: name: manager-role rules: - apiGroups: - - autoscaling + - logic.kubesmarts.org resources: - - horizontalpodautoscalers - verbs: - - get - - list - - watch -- apiGroups: - - batch - resources: - - jobs - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - create - - delete - - get - - list - - update - - watch -- apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - serving.knative.dev - resources: - - revisions - verbs: - - delete - - list - - watch -- apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds - - sonataflowclusterplatforms - - sonataflowplatforms - - sonataflows + - logicflowdefinitions + - logicflowruntimes + - logicflowservices + - logicplatforms verbs: - create - delete @@ -85,22 +20,21 @@ rules: - update - watch - apiGroups: - - sonataflow.org + - logic.kubesmarts.org resources: - - sonataflowbuilds/finalizers - - sonataflowclusterplatforms/finalizers - - sonataflowplatforms/finalizers - - sonataflows/finalizers + - logicflowdefinitions/finalizers + - logicflowruntimes/finalizers + - logicflowservices/finalizers + - logicplatforms/finalizers verbs: - update - apiGroups: - - sonataflow.org + - logic.kubesmarts.org resources: - - sonataflowbuilds/status - - sonataflowclusterplatforms/status - - sonataflowplatforms/status - - sonataflows/scale - - sonataflows/status + - logicflowdefinitions/status + - logicflowruntimes/status + - logicflowservices/status + - logicplatforms/status verbs: - get - patch diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index b44e4697..7024548a 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -1,29 +1,15 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: manager-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: manager-role subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml index 10e2052d..28d62c86 100644 --- a/config/rbac/service_account.yaml +++ b/config/rbac/service_account.yaml @@ -1,22 +1,8 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - apiVersion: v1 kind: ServiceAccount metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager namespace: system diff --git a/config/rbac/service_discovery_role.yaml b/config/rbac/service_discovery_role.yaml deleted file mode 100644 index 29907c2a..00000000 --- a/config/rbac/service_discovery_role.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: service-discovery-role -rules: - - apiGroups: - - apps - resources: - - statefulset - - statefulsets - verbs: - - get - - list - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingress - - ingresses - verbs: - - get - - list - - watch - - apiGroups: - - serving.knative.dev - resources: - - service - - services - verbs: - - get - - list - - watch - - apiGroups: - - eventing.knative.dev - resources: - - broker - - brokers - verbs: - - get - - list - - watch - - apiGroups: - - apps.openshift.io - resources: - - deploymentconfigs - verbs: - - get - - list - - watch - - apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - get - - list - - watch diff --git a/config/rbac/service_discovery_role_binding.yaml b/config/rbac/service_discovery_role_binding.yaml deleted file mode 100644 index d14cf2e2..00000000 --- a/config/rbac/service_discovery_role_binding.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: service-discovery-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: service-discovery-role -subjects: - - kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/sonataflow_editor_role.yaml b/config/rbac/sonataflow_editor_role.yaml deleted file mode 100644 index 042fb358..00000000 --- a/config/rbac/sonataflow_editor_role.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to edit sonataflowworkflows. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowworkflow-editor-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowworkflows - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowworkflows/status - verbs: - - get diff --git a/config/rbac/sonataflow_viewer_role.yaml b/config/rbac/sonataflow_viewer_role.yaml deleted file mode 100644 index e6a12c02..00000000 --- a/config/rbac/sonataflow_viewer_role.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to view sonataflowworkflows. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowworkflow-viewer-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowworkflows - verbs: - - get - - list - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowworkflows/status - verbs: - - get diff --git a/config/rbac/sonataflowbuild_editor_role.yaml b/config/rbac/sonataflowbuild_editor_role.yaml deleted file mode 100644 index 09062563..00000000 --- a/config/rbac/sonataflowbuild_editor_role.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to edit sonataflowworkflowbuilds. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowbuild-editor-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds/status - verbs: - - get diff --git a/config/rbac/sonataflowbuild_viewer_role.yaml b/config/rbac/sonataflowbuild_viewer_role.yaml deleted file mode 100644 index 3a20a838..00000000 --- a/config/rbac/sonataflowbuild_viewer_role.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to view sonataflowworkflowbuilds. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowbuild-viewer-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds - verbs: - - get - - list - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds/status - verbs: - - get diff --git a/config/rbac/sonataflowclusterplatform_editor_role.yaml b/config/rbac/sonataflowclusterplatform_editor_role.yaml deleted file mode 100644 index 910b0b7d..00000000 --- a/config/rbac/sonataflowclusterplatform_editor_role.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to edit sonataflowclusterplatforms. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: sonataflowclusterplatform-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sonataflow-operator - app.kubernetes.io/part-of: sonataflow-operator - app.kubernetes.io/managed-by: kustomize - name: sonataflowclusterplatform-editor-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowclusterplatforms - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowclusterplatforms/status - verbs: - - get diff --git a/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml b/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml deleted file mode 100644 index a1be0afa..00000000 --- a/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# allow users to view SonataFlowClusterPlatforms cluster-wide -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: sonataflowclusterplatform-viewer -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflowclusterplatform-viewer-role -subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated diff --git a/config/rbac/sonataflowclusterplatform_viewer_role.yaml b/config/rbac/sonataflowclusterplatform_viewer_role.yaml deleted file mode 100644 index 0a22c0a0..00000000 --- a/config/rbac/sonataflowclusterplatform_viewer_role.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to view sonataflowclusterplatforms. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: sonataflowclusterplatform-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sonataflow-operator - app.kubernetes.io/part-of: sonataflow-operator - app.kubernetes.io/managed-by: kustomize - name: sonataflowclusterplatform-viewer-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowclusterplatforms - verbs: - - get - - list - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowclusterplatforms/status - verbs: - - get diff --git a/config/rbac/sonataflowplatform_editor_role.yaml b/config/rbac/sonataflowplatform_editor_role.yaml deleted file mode 100644 index 8cb83917..00000000 --- a/config/rbac/sonataflowplatform_editor_role.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to edit sonataflowplatforms. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowplatform-editor-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowplatforms - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowplatforms/status - verbs: - - get diff --git a/config/rbac/sonataflowplatform_viewer_role.yaml b/config/rbac/sonataflowplatform_viewer_role.yaml deleted file mode 100644 index 0abfb64d..00000000 --- a/config/rbac/sonataflowplatform_viewer_role.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# permissions for end users to view sonataflowplatforms. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sonataflowplatform-viewer-role -rules: - - apiGroups: - - sonataflow.org - resources: - - sonataflowplatforms - verbs: - - get - - list - - watch - - apiGroups: - - sonataflow.org - resources: - - sonataflowplatforms/status - verbs: - - get diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 6d4a1897..6b191a46 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -1,24 +1,7 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -## Append samples you want in your CSV to this file as resources ## +## Append samples of your project ## resources: - - sonataflow.org_v1alpha08_sonataflow.yaml - - sonataflow.org_v1alpha08_sonataflowplatform.yaml - - sonataflow.org_v1alpha08_sonataflowbuild.yaml - - sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml -#+kubebuilder:scaffold:manifestskustomizesamples +- logic_v1_logicplatform.yaml +- logic_v1_logicflowservice.yaml +- logic_v1_logicflowdefinition.yaml +- logic_v1_logicflowruntime.yaml +# +kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/logic_v1_logicflowdefinition.yaml b/config/samples/logic_v1_logicflowdefinition.yaml new file mode 100644 index 00000000..a640a539 --- /dev/null +++ b/config/samples/logic_v1_logicflowdefinition.yaml @@ -0,0 +1,9 @@ +apiVersion: logic.kubesmarts.org/v1 +kind: LogicFlowDefinition +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowdefinition-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/logic_v1_logicflowruntime.yaml b/config/samples/logic_v1_logicflowruntime.yaml new file mode 100644 index 00000000..ecf99357 --- /dev/null +++ b/config/samples/logic_v1_logicflowruntime.yaml @@ -0,0 +1,9 @@ +apiVersion: logic.kubesmarts.org/v1 +kind: LogicFlowRuntime +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowruntime-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/logic_v1_logicflowservice.yaml b/config/samples/logic_v1_logicflowservice.yaml new file mode 100644 index 00000000..130333e7 --- /dev/null +++ b/config/samples/logic_v1_logicflowservice.yaml @@ -0,0 +1,9 @@ +apiVersion: logic.kubesmarts.org/v1 +kind: LogicFlowService +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicflowservice-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/logic_v1_logicplatform.yaml b/config/samples/logic_v1_logicplatform.yaml new file mode 100644 index 00000000..23efc15e --- /dev/null +++ b/config/samples/logic_v1_logicplatform.yaml @@ -0,0 +1,9 @@ +apiVersion: logic.kubesmarts.org/v1 +kind: LogicPlatform +metadata: + labels: + app.kubernetes.io/name: logic-operator + app.kubernetes.io/managed-by: kustomize + name: logicplatform-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml b/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml deleted file mode 100644 index 9df80e9a..00000000 --- a/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml +++ /dev/null @@ -1,59 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 -spec: - flow: - start: ChooseOnLanguage - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml b/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml deleted file mode 100644 index 9a62b9a0..00000000 --- a/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml +++ /dev/null @@ -1,87 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -data: - camelroute.xml: ' - - - - ' - camelroute.yaml: "- from: - uri: direct:numberToWords - steps: - - bean: - beanType: java.math.BigInteger - method: valueOf - - setHeader: - name: operationName - constant: NumberToWords - - toD: - uri: cxf://{{com.dataaccess.webservicesserver.url}}?serviceClass=com.dataaccess.webservicesserver.NumberConversionSoapType&wsdlURL=/wsdl/numberconversion.wsdl" -metadata: - name: mycamel-configmap -kind: ConfigMap ---- -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: dev -spec: - resources: - configMaps: - - configMap: - name: mycamel-configmap - flow: - start: ChooseOnLanguage - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml b/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml deleted file mode 100644 index 9009769d..00000000 --- a/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowBuild -metadata: - name: greeting -spec: - timeout: 360s diff --git a/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml b/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml deleted file mode 100644 index 623a8670..00000000 --- a/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowClusterPlatform -metadata: - name: sonataflow-clusterplatform -spec: - platformRef: - name: sonataflow-platform - namespace: sonataflow-operator-system diff --git a/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml b/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml deleted file mode 100644 index 33d18f2b..00000000 --- a/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - registry: - address: host/namespace - secret: regcred diff --git a/config/scorecard/bases/config.yaml b/config/scorecard/bases/config.yaml index 186d88be..c7704784 100644 --- a/config/scorecard/bases/config.yaml +++ b/config/scorecard/bases/config.yaml @@ -1,24 +1,7 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - apiVersion: scorecard.operatorframework.io/v1alpha3 kind: Configuration metadata: name: config stages: - - parallel: true - tests: [] +- parallel: true + tests: [] diff --git a/config/scorecard/kustomization.yaml b/config/scorecard/kustomization.yaml index f614fa41..54e8aa50 100644 --- a/config/scorecard/kustomization.yaml +++ b/config/scorecard/kustomization.yaml @@ -1,33 +1,18 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - resources: - - bases/config.yaml +- bases/config.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization patches: - - path: patches/basic.config.yaml - target: - group: scorecard.operatorframework.io - version: v1alpha3 - kind: Configuration - name: config - - path: patches/olm.config.yaml - target: - group: scorecard.operatorframework.io - version: v1alpha3 - kind: Configuration - name: config -#+kubebuilder:scaffold:patches +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + kind: Configuration + name: config + version: v1alpha3 +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + kind: Configuration + name: config + version: v1alpha3 +# +kubebuilder:scaffold:patches diff --git a/config/scorecard/patches/basic.config.yaml b/config/scorecard/patches/basic.config.yaml index c25b04a5..cc832393 100644 --- a/config/scorecard/patches/basic.config.yaml +++ b/config/scorecard/patches/basic.config.yaml @@ -1,27 +1,10 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - op: add path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.35.0 + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: basic test: basic-check-spec-test diff --git a/config/scorecard/patches/olm.config.yaml b/config/scorecard/patches/olm.config.yaml index be236db2..532bcc24 100644 --- a/config/scorecard/patches/olm.config.yaml +++ b/config/scorecard/patches/olm.config.yaml @@ -1,27 +1,10 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - op: add path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.35.0 + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: olm test: olm-bundle-validation-test @@ -29,9 +12,9 @@ path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.35.0 + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: olm test: olm-crds-have-validation-test @@ -39,9 +22,9 @@ path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.21.0 + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: olm test: olm-crds-have-resources-test @@ -49,9 +32,9 @@ path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.35.0 + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: olm test: olm-spec-descriptors-test @@ -59,9 +42,9 @@ path: /stages/0/tests/- value: entrypoint: - - scorecard-test - - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.35.0 + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.42.2 labels: suite: olm test: olm-status-descriptors-test diff --git a/container-builder/Makefile b/container-builder/Makefile deleted file mode 100644 index f2a95129..00000000 --- a/container-builder/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -.PHONY: all -all: build - -##@ Development -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... - -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... - -.PHONY: test -test: fmt vet ## Run tests. - go test ./... -coverprofile cover.out - -##@ Build - -.PHONY: build -build: fmt vet ## Build manager binary. - go build -o bin/builder main.go - -.PHONY: run -run: fmt vet ## Run a controller from your host. - go run ./main.go - -##@ Build Dependencies - -.PHONY: clean -clean: - rm -rf bin/ - -.PHONY: docker-integration-test -docker-integration-test: ## Test docker integration tests - go test ./... -tags integration_docker - -.PHONY: kaniko-docker-integration-test -kaniko-docker-integration-test: ## Test kaniko integration docker tests - go test ./... -tags integration_kaniko_docker diff --git a/container-builder/README.md b/container-builder/README.md deleted file mode 100644 index 70b0efcc..00000000 --- a/container-builder/README.md +++ /dev/null @@ -1,174 +0,0 @@ - - -# Container Builder - -This is an internal build system implementation inspired by [Camel-K Builder package](https://github.com/apache/camel-k/tree/main/pkg/builder) to build Kogito services in a Kubernetes clusters. - -It supports [Kaniko](https://github.com/GoogleContainerTools/kaniko/blob/main/docs/tutorial.md) as the builder implementation. - -## Requirements - -To run it on minikube, you can do: - -- Install minikube locally -- Enable the internal registry via `minikube addons enable registry` -- Run with `go run main.go` - -Please note that the [`main.go`](main.go) file is a usage example. _Don't use it in production level code_. - -## History - -Since Camel-K already does a pretty good job building Camel applications in any Kubernetes environments and has a quite similar use case to Kogito, it makes sense looking at their tech. - -## How does it work? - -Camel-K has basically two phases of their build, which are "Project Assemble" and "Image Build". -In this first phase, Camel-K reads the Route configuration, assemble the Maven project and run the project build. -Then it takes the Java application and build into an image. - -Camel-K has this concept of "Environment Platform" that is based on the type of cluster in use, so it can pick the right build feature. -For example, source to image on OpenShift clusters or Kaniko on Kubernetes. - -Kogito might use this first phase to assemble a specific application based on the sources pushed to the cluster. -For simplicity, we skipped this first phase and assembled the project on a "builder image" for Serverless Workflow projects. -You can see a [draft for this image here](https://github.com/kiegroup/kogito-images/pull/1322). - -This base builder image does the project assembling "ahead of time", so there's no need to run this phase like Camel-K does. -Kogito won't need this level of customization of a project, but there are use cases which could benefit from it such as using MongoDB as the persistence layer rather than Postgres. - -This package performs the Camel-K builder just partially, but using their interfaces and structures to have some sort of compatibility. -Ideally, this project will evolve to a shared builder that can be reused by the tools from Camel-K and Kogito. - -The package is not a Kubernetes Operator, but rather a set of packages that could be embedded on an operator running in a cluster or a CLI running locally. - -The concept behind it is really simple. It abstracts the build and delegates internally based on the `PlatformBuild` information. -The builder chosen by the environment will run and the final image pushed to the elected registry. - -This initial work supports Kaniko running on Minikube. Has potential to work on Kubernetes with an external registry such as Quay or Dockerhub. - -## The Next Steps - -This package can evolve to do more and abstract the build stage for a shareable use among Kaniko and Camel-K. - -In a nutshell, a few EPICs: - -- Run tests on different environments to validate Kaniko on OpenShift, KIND, and Kubernetes. -- Implement other build implementations such as [Spectrum](https://github.com/container-tools/spectrum), local Podman/Docker run, and [Source to Image](https://github.com/openshift/source-to-image). -- Implement the first stage: "Project Assemble" instead of relying on a pre-built, pre-configured image. -- Review the API interfaces and types to make sure that aligns with the build abstraction and can cover the majority of use cases. - -Keep in mind that the end goal is to use this package anywhere you can run a Go application. - -As we evolve, evaluate the package with Camel-K team to make sure that it can fit their use case the same way it does today with their embedded package. -That might require some work to remove the relation of the integration concept from the build tasks. - -## Docker Registry configuration - -If you want to connect on a remote Docker registry we must set the following environment variables: - -- **DOCKER_HOST**: sets the url to the docker server. -- **DOCKER_API_VERSION**: sets the version of the API to reach, leave empty for latest. -- **DOCKER_CERT_PATH**: loads the TLS certificates from. -- **DOCKER_TLS_VERIFY**: enables or disable TLS verification, off by default. - -otherwise a local docker registry will be used if nothing is present - -## Podman Registry configuration - -To connect on a remote Podman registry we can use one of the following uri connections: - -- tcp://localhost: -- unix:///run/podman/podman.sock -- ssh://@[:port]/run/podman/podman.sock?secure=True - -To connect with a remote server we must set as environment variables the follows: -Envs - -- CONTAINER_HOST -- CONTAINER_SSHKEY -- CONTAINER_PASSPHRASE - -Otherwise, for local connection will be used the env var - -- XDG_RUNTIME_DIR - -with ROOTLESS access -unix://run/user/1000/podman/podman.sock - -Note start the podman rootless socket with: -`systemctl --user start podman.socket` - -To start podman root mode -`systemctl start podman.socket` - -Problems on test with SELinux -`sudo setenforce Permissive` - -Development debug -`podman --log-level=debug system service -t 0` - -`journalctl --user --no-pager -u podman.socket` - -Problems on mixing sysregistry v1/v2 is not supported -add on /etc/containers/registries.conf -`[[registry]] -insecure = true -location = "localhost:5000"` - -NOTE on Registry container -TO enable the images deletion you need to set the following environment variable: - -```bash -REGISTRY_STORAGE_DELETE_ENABLED=true -``` - -otherwise it will return an HTTP 405 error (Not Allowed). - -## Kaniko Vanilla - -Kaniko Vanilla is our API to run a Kaniko build outside Kubernetes Cluster -when it is needed to measure the time of a dockerfile to correctly improve the operations. - -To run Kaniko locally first we need to start a local registry: - -```sh -docker run -d -p 5000:5000 --name registry registry:latest -``` - -then after replaced with your current user and with your current project path -run a build with - -```sh -docker run \ - --net=host \ - -v //examples:/workspace \ - -v /home//.docker/config.json:/root/.docker/config.json \ - -e DOCKER_CONFIG=/root/.docker \ - gcr.io/kaniko-project/executor:latest \ - -f /workspace/dockerfiles/Kogito.dockerfile \ - -d localhost:5000/kaniko-test/kaniko-dockerfile_test_swf \ - --force \ - -c /workspace \ - --verbosity debug -``` - -to see the image in the container registry open your browser at the address: - -```sh -http://localhost:5000/v2/_catalog -``` diff --git a/container-builder/api/build_types.go b/container-builder/api/build_types.go deleted file mode 100644 index 293c6c1b..00000000 --- a/container-builder/api/build_types.go +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 api - -import ( - "fmt" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// ContainerBuild is the Schema for the builder API. Follows the Kubernetes resource structure, but it's not tied to it. Can be used in any environment. -type ContainerBuild struct { - ObjectReference `json:"metadata,omitempty"` - Spec ContainerBuildSpec `json:"spec,omitempty"` - Status ContainerBuildStatus `json:"status,omitempty"` -} - -// ContainerBuildStrategy specifies how the ContainerBuild should be executed. -// It will trigger a Maven process that will take care of producing the expected runtime. -// +kubebuilder:validation:Enum=routine;pod -type ContainerBuildStrategy string - -const ( - // ContainerBuildStrategyRoutine performs the build in a routine (will be executed as a process inside the same owner `Pod` or local process). - // A routine may be preferred to a `pod` strategy since it reuse the Maven repository dependency cached locally. It is executed as - // a parallel process, so you may need to consider the quantity of concurrent build process running simultaneously. - ContainerBuildStrategyRoutine ContainerBuildStrategy = "routine" - // ContainerBuildStrategyPod performs the build in a `Pod` (will schedule a new builder ephemeral `Pod` which will take care of the build action). - // This strategy has the limitation that every build will have to download all the dependencies required by the Maven build. - ContainerBuildStrategyPod ContainerBuildStrategy = "pod" -) - -// ContainerBuildSpec defines the ContainerBuild operation to be executed -type ContainerBuildSpec struct { - // The sequence of ContainerBuild tasks to be performed as part of the ContainerBuild execution. - Tasks []ContainerBuildTask `json:"tasks,omitempty"` - // The strategy that should be used to perform the ContainerBuild. - Strategy ContainerBuildStrategy `json:"strategy,omitempty"` - // Timeout defines the ContainerBuild maximum execution duration. - // The ContainerBuild deadline is set to the ContainerBuild start time plus the Timeout duration. - // If the ContainerBuild deadline is exceeded, the ContainerBuild context is canceled, - // and its phase set to ContainerBuildPhaseFailed. - // +kubebuilder:validation:Format=duration - Timeout metav1.Duration `json:"timeout,omitempty"` -} - -// ContainerRegistrySpec provides the configuration for the container registry -type ContainerRegistrySpec struct { - // if the container registry is insecure (ie, http only) - Insecure bool `json:"insecure,omitempty"` - // the URI to access - Address string `json:"address,omitempty"` - // the secret where credentials are stored - Secret string `json:"secret,omitempty"` - // the configmap which stores the Certificate Authority - CA string `json:"ca,omitempty"` - // the registry organization - Organization string `json:"organization,omitempty"` -} - -// ContainerBuildTask represents the abstract task. Only one of the task should be configured to represent the specific task chosen. -type ContainerBuildTask struct { - // a KanikoTask, for Kaniko strategy - Kaniko *KanikoTask `json:"kaniko,omitempty"` -} - -// ContainerBuildBaseTask is a base for the struct hierarchy -type ContainerBuildBaseTask struct { - // name of the task - Name string `json:"name,omitempty"` - // Resources -- optional compute resource requirements for the Kaniko container - Resources corev1.ResourceRequirements `json:"resources,omitempty"` - // Build arguments passed to the internal build system (e.g. Dockerfile ARG) - BuildArgs []corev1.EnvVar - // Environment variable passed to the internal build container. - Envs []corev1.EnvVar `json:"envs,omitempty"` -} - -// PublishTask image publish configuration -type PublishTask struct { - // can be useful to share info with other tasks - ContextDir string `json:"contextDir,omitempty"` - // base image layer - BaseImage string `json:"baseImage,omitempty"` - // final image name - Image string `json:"image,omitempty"` - // where to publish the final image - Registry ContainerRegistrySpec `json:"registry,omitempty"` -} - -// GetRepositoryImageTag gets the full qualified Repository Name for the given image in the PublishTask. -// For example registry.org/myrepo/myimage:latest. -func (p *PublishTask) GetRepositoryImageTag() string { - if len(p.Registry.Address) > 0 { - return fmt.Sprintf("%s/%s", p.Registry.Address, p.Image) - } - return p.Image -} - -// KanikoTask is used to configure Kaniko -type KanikoTask struct { - ContainerBuildBaseTask `json:",inline"` - PublishTask `json:",inline"` - // log more information - Verbose *bool `json:"verbose,omitempty"` - // use a cache - Cache KanikoTaskCache `json:"cache,omitempty"` - // AdditionalFlags -- List of additional flags for the Kaniko process (see https://github.com/GoogleContainerTools/kaniko/blob/main/README.md#additional-flags) - AdditionalFlags []string `json:"additionalFlags,omitempty"` - // Image used by the created Kaniko pod executor - KanikoExecutorImage string `json:"kanikoExecutorImage,omitempty"` -} - -// KanikoTaskCache is used to configure Kaniko cache -type KanikoTaskCache struct { - // true if a cache is enabled - Enabled *bool `json:"enabled,omitempty"` - // the PVC used to store the cache - PersistentVolumeClaim string `json:"persistentVolumeClaim,omitempty"` -} - -// ContainerBuildPhase -- -type ContainerBuildPhase string - -const ( - // ContainerBuildPhaseNone -- - ContainerBuildPhaseNone ContainerBuildPhase = "" - // ContainerBuildPhaseInitialization -- - ContainerBuildPhaseInitialization ContainerBuildPhase = "Initialization" - // ContainerBuildPhaseScheduling -- - ContainerBuildPhaseScheduling ContainerBuildPhase = "Scheduling" - // ContainerBuildPhasePending -- - ContainerBuildPhasePending ContainerBuildPhase = "Pending" - // ContainerBuildPhaseRunning -- - ContainerBuildPhaseRunning ContainerBuildPhase = "Running" - // ContainerBuildPhaseSucceeded -- - ContainerBuildPhaseSucceeded ContainerBuildPhase = "Succeeded" - // ContainerBuildPhaseFailed -- - ContainerBuildPhaseFailed ContainerBuildPhase = "Failed" - // ContainerBuildPhaseInterrupted -- - ContainerBuildPhaseInterrupted ContainerBuildPhase = "Interrupted" - // ContainerBuildPhaseError -- - ContainerBuildPhaseError ContainerBuildPhase = "Error" -) - -// ContainerBuildConditionType -- -type ContainerBuildConditionType string - -// ContainerBuildCondition describes the state of a resource at a certain point. -type ContainerBuildCondition struct { - // Type of integration condition. - Type ContainerBuildConditionType `json:"type"` - // Status of the condition, one of True, False, Unknown. - Status corev1.ConditionStatus `json:"status"` - // The last time this condition was updated. - LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` - // Last time the condition transitioned from one status to another. - LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` - // The reason for the condition's last transition. - Reason string `json:"reason,omitempty"` - // A human-readable message indicating details about the transition. - Message string `json:"message,omitempty"` -} - -// ContainerBuildStatus defines the observed state of ContainerBuild -type ContainerBuildStatus struct { - // ObservedGeneration is the most recent generation observed for this ContainerBuild. - ObservedGeneration int64 `json:"observedGeneration,omitempty"` - // describes the phase - Phase ContainerBuildPhase `json:"phase,omitempty"` - // the image name built - RepositoryImageTag string `json:"repositoryImageTag,omitempty"` - // the digest from image - Digest string `json:"digest,omitempty"` - // the base image used for this build - BaseImage string `json:"baseImage,omitempty"` - // the error description (if any) - Error string `json:"error,omitempty"` - // the reason of the failure (if any) - Failure *ContainerBuildFailure `json:"failure,omitempty"` - // the time when it started - StartedAt *metav1.Time `json:"startedAt,omitempty"` - // a list of conditions occurred during the build - Conditions []ContainerBuildCondition `json:"conditions,omitempty"` - // how long it took for the build - // Change to Duration / ISO 8601 when CRD uses OpenAPI spec v3 - // https://github.com/OAI/OpenAPI-Specification/issues/845 - Duration string `json:"duration,omitempty"` - // reference to where the build resources are located - ResourceVolumes []ContainerBuildResourceVolume `json:"resourceVolumes,omitempty"` -} - -// ContainerBuildFailure represent a message specifying the reason and the time of an event failure -type ContainerBuildFailure struct { - // a short text specifying the reason - Reason string `json:"reason"` - // the time when the failure has happened - Time metav1.Time `json:"time"` - // the recovery attempted for this failure - Recovery ContainerBuildFailureRecovery `json:"recovery"` -} - -// ContainerBuildFailureRecovery defines the attempts to recover a failure -type ContainerBuildFailureRecovery struct { - // attempt number - Attempt int `json:"attempt"` - // maximum number of attempts - AttemptMax int `json:"attemptMax"` - // time of the attempt execution - // +optional - AttemptTime metav1.Time `json:"attemptTime"` -} - -type ContainerBuildResourceReferenceType string - -const ( - ResourceReferenceTypeConfigMap ContainerBuildResourceReferenceType = "configMap" -) - -// ContainerBuildResourceVolume dictates where the build resources are mount -type ContainerBuildResourceVolume struct { - // ReferenceName name of the object holding the resources reference - ReferenceName string `json:"referenceName"` - // ReferenceType type of the resource holding the reference - ReferenceType ContainerBuildResourceReferenceType `json:"referenceType"` - // DestinationDir where to mount the given volume in the build context - DestinationDir string `json:"destinationDir,omitempty"` -} diff --git a/container-builder/api/common_type.go b/container-builder/api/common_type.go deleted file mode 100644 index 540c1c3d..00000000 --- a/container-builder/api/common_type.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 api - -import ( - "k8s.io/apimachinery/pkg/types" -) - -// ObjectReference is a subset of the kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface. -// Objects in this API not necessarily represent Kubernetes objects, but this structure can help when needed. -type ObjectReference struct { - Namespace string `json:"namespace,omitempty"` - Name string `json:"name,omitempty"` -} - -func (o *ObjectReference) GetName() string { - return o.Name -} - -func (o *ObjectReference) GetNamespace() string { - return o.Namespace -} - -func (o *ObjectReference) GetObjectKey() types.NamespacedName { - return types.NamespacedName{Name: o.Name, Namespace: o.Namespace} -} diff --git a/container-builder/api/doc.go b/container-builder/api/doc.go deleted file mode 100644 index 75dfbd19..00000000 --- a/container-builder/api/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// +k8s:deepcopy-gen=package - -package api diff --git a/container-builder/api/platform_types.go b/container-builder/api/platform_types.go deleted file mode 100644 index 51a47d32..00000000 --- a/container-builder/api/platform_types.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 api - -import ( - "strconv" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -type PlatformContainerBuild struct { - ObjectReference `json:"meta,omitempty"` - Spec PlatformContainerBuildSpec `json:"spec,omitempty"` -} - -type PlatformContainerBuildSpec struct { - // the strategy to adopt for building a base image - BuildStrategy ContainerBuildStrategy `json:"buildStrategy,omitempty"` - // the strategy to adopt for publishing a base image - PublishStrategy PlatformContainerBuildPublishStrategy `json:"publishStrategy,omitempty"` - // a base image that can be used as base layer for all images. - // It can be useful if you want to provide some custom base image with further utility software - BaseImage string `json:"baseImage,omitempty"` - // the image registry used to push/pull built images - Registry ContainerRegistrySpec `json:"registry,omitempty"` - // how much time to wait before time out the build process - Timeout *metav1.Duration `json:"timeout,omitempty"` - // - BuildStrategyOptions map[string]string `json:"BuildStrategyOptions,omitempty"` -} - -// PlatformContainerBuildPublishStrategy defines the strategy used to package and publish an Integration base image -type PlatformContainerBuildPublishStrategy string - -const ( - // PlatformBuildPublishStrategyKaniko uses Kaniko project (https://github.com/GoogleContainerTools/kaniko) - // in order to push the incremental images to the image repository. It can be used with `pod` ContainerBuildStrategy. - PlatformBuildPublishStrategyKaniko PlatformContainerBuildPublishStrategy = "Kaniko" -) - -// IsOptionEnabled return whether if the BuildStrategyOptions is enabled or not -func (b *PlatformContainerBuildSpec) IsOptionEnabled(option string) bool { - //Key defined in builder/kaniko.go - if enabled, ok := b.BuildStrategyOptions[option]; ok { - res, err := strconv.ParseBool(enabled) - if err != nil { - return false - } - return res - } - return false -} - -// GetTimeout returns the specified duration or a default one -func (b *PlatformContainerBuildSpec) GetTimeout() metav1.Duration { - if b.Timeout == nil { - return metav1.Duration{} - } - return *b.Timeout -} diff --git a/container-builder/api/zz_generated.deepcopy.go b/container-builder/api/zz_generated.deepcopy.go deleted file mode 100644 index 2afe5c22..00000000 --- a/container-builder/api/zz_generated.deepcopy.go +++ /dev/null @@ -1,357 +0,0 @@ -//go:build !ignore_autogenerated - -/* - * Copyright 2026 The Kubesmarts 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 controller-gen. DO NOT EDIT. - -package api - -import ( - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuild) DeepCopyInto(out *ContainerBuild) { - *out = *in - out.ObjectReference = in.ObjectReference - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuild. -func (in *ContainerBuild) DeepCopy() *ContainerBuild { - if in == nil { - return nil - } - out := new(ContainerBuild) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildBaseTask) DeepCopyInto(out *ContainerBuildBaseTask) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - if in.BuildArgs != nil { - in, out := &in.BuildArgs, &out.BuildArgs - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Envs != nil { - in, out := &in.Envs, &out.Envs - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildBaseTask. -func (in *ContainerBuildBaseTask) DeepCopy() *ContainerBuildBaseTask { - if in == nil { - return nil - } - out := new(ContainerBuildBaseTask) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildCondition) DeepCopyInto(out *ContainerBuildCondition) { - *out = *in - in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) - in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildCondition. -func (in *ContainerBuildCondition) DeepCopy() *ContainerBuildCondition { - if in == nil { - return nil - } - out := new(ContainerBuildCondition) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildFailure) DeepCopyInto(out *ContainerBuildFailure) { - *out = *in - in.Time.DeepCopyInto(&out.Time) - in.Recovery.DeepCopyInto(&out.Recovery) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildFailure. -func (in *ContainerBuildFailure) DeepCopy() *ContainerBuildFailure { - if in == nil { - return nil - } - out := new(ContainerBuildFailure) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildFailureRecovery) DeepCopyInto(out *ContainerBuildFailureRecovery) { - *out = *in - in.AttemptTime.DeepCopyInto(&out.AttemptTime) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildFailureRecovery. -func (in *ContainerBuildFailureRecovery) DeepCopy() *ContainerBuildFailureRecovery { - if in == nil { - return nil - } - out := new(ContainerBuildFailureRecovery) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildResourceVolume) DeepCopyInto(out *ContainerBuildResourceVolume) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildResourceVolume. -func (in *ContainerBuildResourceVolume) DeepCopy() *ContainerBuildResourceVolume { - if in == nil { - return nil - } - out := new(ContainerBuildResourceVolume) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildSpec) DeepCopyInto(out *ContainerBuildSpec) { - *out = *in - if in.Tasks != nil { - in, out := &in.Tasks, &out.Tasks - *out = make([]ContainerBuildTask, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - out.Timeout = in.Timeout -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildSpec. -func (in *ContainerBuildSpec) DeepCopy() *ContainerBuildSpec { - if in == nil { - return nil - } - out := new(ContainerBuildSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildStatus) DeepCopyInto(out *ContainerBuildStatus) { - *out = *in - if in.Failure != nil { - in, out := &in.Failure, &out.Failure - *out = new(ContainerBuildFailure) - (*in).DeepCopyInto(*out) - } - if in.StartedAt != nil { - in, out := &in.StartedAt, &out.StartedAt - *out = (*in).DeepCopy() - } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]ContainerBuildCondition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.ResourceVolumes != nil { - in, out := &in.ResourceVolumes, &out.ResourceVolumes - *out = make([]ContainerBuildResourceVolume, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildStatus. -func (in *ContainerBuildStatus) DeepCopy() *ContainerBuildStatus { - if in == nil { - return nil - } - out := new(ContainerBuildStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerBuildTask) DeepCopyInto(out *ContainerBuildTask) { - *out = *in - if in.Kaniko != nil { - in, out := &in.Kaniko, &out.Kaniko - *out = new(KanikoTask) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerBuildTask. -func (in *ContainerBuildTask) DeepCopy() *ContainerBuildTask { - if in == nil { - return nil - } - out := new(ContainerBuildTask) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContainerRegistrySpec) DeepCopyInto(out *ContainerRegistrySpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerRegistrySpec. -func (in *ContainerRegistrySpec) DeepCopy() *ContainerRegistrySpec { - if in == nil { - return nil - } - out := new(ContainerRegistrySpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KanikoTask) DeepCopyInto(out *KanikoTask) { - *out = *in - in.ContainerBuildBaseTask.DeepCopyInto(&out.ContainerBuildBaseTask) - out.PublishTask = in.PublishTask - if in.Verbose != nil { - in, out := &in.Verbose, &out.Verbose - *out = new(bool) - **out = **in - } - in.Cache.DeepCopyInto(&out.Cache) - if in.AdditionalFlags != nil { - in, out := &in.AdditionalFlags, &out.AdditionalFlags - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KanikoTask. -func (in *KanikoTask) DeepCopy() *KanikoTask { - if in == nil { - return nil - } - out := new(KanikoTask) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KanikoTaskCache) DeepCopyInto(out *KanikoTaskCache) { - *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 KanikoTaskCache. -func (in *KanikoTaskCache) DeepCopy() *KanikoTaskCache { - if in == nil { - return nil - } - out := new(KanikoTaskCache) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference. -func (in *ObjectReference) DeepCopy() *ObjectReference { - if in == nil { - return nil - } - out := new(ObjectReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformContainerBuild) DeepCopyInto(out *PlatformContainerBuild) { - *out = *in - out.ObjectReference = in.ObjectReference - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformContainerBuild. -func (in *PlatformContainerBuild) DeepCopy() *PlatformContainerBuild { - if in == nil { - return nil - } - out := new(PlatformContainerBuild) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlatformContainerBuildSpec) DeepCopyInto(out *PlatformContainerBuildSpec) { - *out = *in - out.Registry = in.Registry - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(metav1.Duration) - **out = **in - } - if in.BuildStrategyOptions != nil { - in, out := &in.BuildStrategyOptions, &out.BuildStrategyOptions - *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 PlatformContainerBuildSpec. -func (in *PlatformContainerBuildSpec) DeepCopy() *PlatformContainerBuildSpec { - if in == nil { - return nil - } - out := new(PlatformContainerBuildSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PublishTask) DeepCopyInto(out *PublishTask) { - *out = *in - out.Registry = in.Registry -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PublishTask. -func (in *PublishTask) DeepCopy() *PublishTask { - if in == nil { - return nil - } - out := new(PublishTask) - in.DeepCopyInto(out) - return out -} diff --git a/container-builder/builder/kaniko_docker_integration_test.go b/container-builder/builder/kaniko_docker_integration_test.go deleted file mode 100644 index 90248a35..00000000 --- a/container-builder/builder/kaniko_docker_integration_test.go +++ /dev/null @@ -1,68 +0,0 @@ -//go:build integration_kaniko_docker - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "os" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -func TestKanikoTestSuite(t *testing.T) { - suite.Run(t, new(KanikoDockerTestSuite)) -} - -func (suite *KanikoDockerTestSuite) TestKanikoBuild() { - imageName := "localhost:5000/kaniko-test/kaniko-dockerfile_test_swf" - //@TODO investigate when the code will be in the mono repo - //registry, err, repos := checkEmptyDockerRegistry(suite) - mydir, err := os.Getwd() - if err != nil { - klog.V(log.E).ErrorS(err, "error getting working directory.") - } - dockefileDir := mydir + "/../examples/dockerfiles" - assert.Nil(suite.T(), suite.Docker.PullImage(executorImage), "Pull image failed") - config := KanikoVanillaConfig{ - DockerFilePath: dockefileDir, - VerbosityLevel: "info", - KanikoExecutorImage: executorImage, - ContainerName: "kaniko-build", - DockerFileName: "SonataFlow.dockerfile", - RegistryFinalImageName: imageName, - ReadBuildOutput: false, - } - klog.V(log.I).InfoS("Start Kaniko build") - start := time.Now() - imageID, err := KanikoBuild(suite.Docker.Connection, config) - timeElapsed := time.Since(start) - klog.V(log.I).InfoS("The Kaniko build took", "duration", timeElapsed) - assert.Nil(suite.T(), err, "ContainerBuild failed") - assert.NotNil(suite.T(), imageID, err, "ContainerBuild failed") - //@TODO investigate when the code will be in the mono repo - //checkImageOnDockerRegistry(suite, imageName, repos, registry) -} diff --git a/container-builder/builder/kaniko_integration_test_suite.go b/container-builder/builder/kaniko_integration_test_suite.go deleted file mode 100644 index 524ec0a9..00000000 --- a/container-builder/builder/kaniko_integration_test_suite.go +++ /dev/null @@ -1,77 +0,0 @@ -//go:build integration_kaniko_docker - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/common" - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -type KanikoDockerTestSuite struct { - suite.Suite - LocalRegistry common.DockerLocalRegistry - RegistryID string - Docker common.Docker -} - -func (suite *KanikoDockerTestSuite) SetupSuite() { - dockerRegistryContainer, registryID, docker := common.SetupDockerSocket() - if len(registryID) > 0 { - suite.LocalRegistry = dockerRegistryContainer - suite.RegistryID = registryID - suite.Docker = docker - } else { - assert.FailNow(suite.T(), "Initialization failed %s", registryID) - } - - pullErr := suite.Docker.PullImage(executorImage) - if pullErr != nil { - klog.V(log.E).ErrorS(pullErr, "Pull Kaniko executor") - } - time.Sleep(4 * time.Second) // Needed on CI -} - -func (suite *KanikoDockerTestSuite) TearDownSuite() { - registryID := suite.LocalRegistry.GetRegistryRunningID() - if len(registryID) > 0 { - common.DockerTearDown(suite.LocalRegistry) - } else { - suite.LocalRegistry.StopRegistry() - } - purged, err := suite.Docker.PurgeContainer("", common.RegistryImg) - klog.V(log.I).InfoS("Purged containers", "containers", purged) - if err != nil { - klog.V(log.E).ErrorS(err, "Purged registry") - } - - purgedBuild, err := suite.Docker.PurgeContainer("", executorImage) - if err != nil { - klog.V(log.E).ErrorS(err, "Purged container") - } - klog.V(log.I).InfoS("Purged container build", "container", purgedBuild) -} diff --git a/container-builder/builder/kaniko_vanilla.go b/container-builder/builder/kaniko_vanilla.go deleted file mode 100644 index 8ce1e3a5..00000000 --- a/container-builder/builder/kaniko_vanilla.go +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - "os" - - "k8s.io/klog/v2" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/stdcopy" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -type KanikoVanillaConfig struct { - DockerFilePath string - KanikoExecutorImage string - DockerFileName string - RegistryFinalImageName string - VerbosityLevel string - ContainerName string - ReadBuildOutput bool -} - -const executorImage = "gcr.io/kaniko-project/executor:latest" - -func KanikoBuild(connection *client.Client, config KanikoVanillaConfig) (string, error) { - - hostConfig := &container.HostConfig{ - NetworkMode: "host", - Binds: []string{ - config.DockerFilePath + ":/workspace", - }, - } - - ctx := context.Background() - resp, err := connection.ContainerCreate(ctx, &container.Config{ - Image: config.KanikoExecutorImage, - Cmd: []string{ - "-f", config.DockerFileName, - "-d", config.RegistryFinalImageName, - "-c", "/workspace", - "--force", - "--verbosity", config.VerbosityLevel, - }, - Tty: false, - Volumes: map[string]struct{}{}, - }, hostConfig, nil, nil, config.ContainerName) - - if err != nil { - klog.V(log.E).ErrorS(err, "error during KanikoBuild, ContainerCreate") - } - - if err := connection.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { - klog.V(log.E).ErrorS(err, "error during KanikoBuild, ContainerStart") - } - - statusCh, errCh := connection.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) - select { - case err := <-errCh: - if err != nil { - klog.V(log.E).ErrorS(err, "error during KanikoBuild, ContainerWait") - } - case <-statusCh: - } - - out, err := connection.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during KanikoBuild, ContainerLogs") - } - if config.ReadBuildOutput { - stdcopy.StdCopy(os.Stdout, os.Stderr, out) - } - return resp.ID, err -} diff --git a/container-builder/builder/kubernetes/action.go b/container-builder/builder/kubernetes/action.go deleted file mode 100644 index 0f35762d..00000000 --- a/container-builder/builder/kubernetes/action.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -type Action interface { - client.Injectable - // Name returns user-friendly name for the action - Name() string - - // CanHandle returns true if the action can handle the build - CanHandle(build *api.ContainerBuild) bool - - // Handle executes the handling function - Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) -} - -type baseAction struct { - client client.Client -} - -// TODO: implement our client wrapper - -func (action *baseAction) InjectClient(client client.Client) { - action.client = client -} diff --git a/container-builder/builder/kubernetes/build_pod.go b/container-builder/builder/kubernetes/build_pod.go deleted file mode 100644 index 5836cd19..00000000 --- a/container-builder/builder/kubernetes/build_pod.go +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "os" - "path" - "strings" - - "github.com/pkg/errors" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - - "github.com/kubesmarts/logic-operator/container-builder/client" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -type registrySecret struct { - fileName string - mountPath string - destination string - refEnv string -} - -func newBuildPod(ctx context.Context, c client.Client, build *api.ContainerBuild) (*corev1.Pod, error) { - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: build.Namespace, - Name: buildPodName(build), - Labels: map[string]string{ - "sonataflow.org/containerBuildContext": build.Name, - "sonataflow.org/component": "builder", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - }, - } - - for _, task := range build.Spec.Tasks { - switch { - case task.Kaniko != nil: - err := addKanikoTaskToPod(ctx, c, build, task.Kaniko, pod) - if err != nil { - return nil, err - } - } - } - - return pod, nil -} - -func buildPodName(build *api.ContainerBuild) string { - return "sonataflow-" + strings.ToLower(build.Name) + "-builder" -} - -func getBuilderPod(ctx context.Context, c client.Client, build *api.ContainerBuild) (*corev1.Pod, error) { - pod := corev1.Pod{} - err := c.Get(ctx, types.NamespacedName{Name: buildPodName(build), Namespace: build.Namespace}, &pod) - if err != nil && k8serrors.IsNotFound(err) { - return nil, nil - } - if err != nil { - return nil, err - } - - return &pod, nil -} - -func deleteBuilderPod(ctx context.Context, c client.Client, build *api.ContainerBuild) error { - pod := corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: build.Namespace, - Name: buildPodName(build), - }, - } - - err := c.Delete(ctx, &pod) - if err != nil && k8serrors.IsNotFound(err) { - return nil - } - - return err -} - -func getRegistrySecret(ctx context.Context, c client.Client, ns, name string, registrySecrets []registrySecret) (registrySecret, error) { - secret := corev1.Secret{} - err := c.Get(ctx, types.NamespacedName{Name: name, Namespace: ns}, &secret) - if err != nil { - return registrySecret{}, err - } - for _, k := range registrySecrets { - if _, ok := secret.Data[k.fileName]; ok { - return k, nil - } - } - return registrySecret{}, errors.New("unsupported secret type for registry authentication") -} - -func addRegistrySecret(name string, secret registrySecret, volumes *[]corev1.Volume, volumeMounts *[]corev1.VolumeMount, env *[]corev1.EnvVar) { - *volumes = append(*volumes, corev1.Volume{ - Name: "registry-secret", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: name, - Items: []corev1.KeyToPath{ - { - Key: secret.fileName, - Path: secret.destination, - }, - }, - }, - }, - }) - - *volumeMounts = append(*volumeMounts, corev1.VolumeMount{ - Name: "registry-secret", - MountPath: secret.mountPath, - ReadOnly: true, - }) - - if secret.refEnv != "" { - *env = append(*env, corev1.EnvVar{ - Name: secret.refEnv, - Value: path.Join(secret.mountPath, secret.destination), - }) - } -} - -func proxyFromEnvironment() []corev1.EnvVar { - var envVars []corev1.EnvVar - - if httpProxy, ok := os.LookupEnv("HTTP_PROXY"); ok { - envVars = append(envVars, corev1.EnvVar{ - Name: "HTTP_PROXY", - Value: httpProxy, - }) - } - - if httpsProxy, ok := os.LookupEnv("HTTPS_PROXY"); ok { - envVars = append(envVars, corev1.EnvVar{ - Name: "HTTPS_PROXY", - Value: httpsProxy, - }) - } - - if noProxy, ok := os.LookupEnv("NO_PROXY"); ok { - envVars = append(envVars, corev1.EnvVar{ - Name: "NO_PROXY", - Value: noProxy, - }) - } - - return envVars -} diff --git a/container-builder/builder/kubernetes/builder.go b/container-builder/builder/kubernetes/builder.go deleted file mode 100644 index 68550f24..00000000 --- a/container-builder/builder/kubernetes/builder.go +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "fmt" - - "k8s.io/klog/v2" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -type BuilderProperty string - -const KanikoCache BuilderProperty = "kaniko-cache" - -type ContainerBuilderInfo struct { - FinalImageName string - BuildUniqueName string - Platform api.PlatformContainerBuild - // ContainerBuilderImageTag the image tag used internally to create the pod builder (e.g. Kaniko Executor Builder image) - ContainerBuilderImageTag string -} - -type resource struct { - Target string - Content []byte - Path string -} - -type resourceConfigMap struct { - Ref corev1.LocalObjectReference - Path string -} - -type containerBuildContext struct { - c client.Client - ctx context.Context - containerBuild *api.ContainerBuild - baseImage string -} - -type reconciler struct { - containerBuildContext *containerBuildContext -} - -type mountHandler struct { - containerBuildContext *containerBuildContext - reconciler *reconciler - info ContainerBuilderInfo - resources []resource - resourceConfigMaps []resourceConfigMap -} - -type schedulerHook func() (*api.ContainerBuild, error) - -var _ Reconciler = &reconciler{} -var _ MountHandler = &mountHandler{} - -// available schedulers, add them in priority order -var schedulers = map[string]schedulerManager{ - "kaniko": &kanikoSchedulerManager{}, -} - -// Scheduler provides an interface to add resources and schedule a new build -type Scheduler interface { - // WithResourceRequirements Kubernetes resource requirements to be passed to the underlying builder if necessary. For example, a builder pod might require specific resources underneath. - WithResourceRequirements(res corev1.ResourceRequirements) Scheduler - // WithAdditionalArgs array of strings to pass to the underlying builder. For example "--myarg=myvalue" or "MY_ENV=MY_VALUE". The args are passed separated by spaces. - WithAdditionalArgs(args []string) Scheduler - // WithProperty specialized property known by inner implementations for additional properties to configure the underlying builder - WithProperty(property BuilderProperty, object interface{}) Scheduler - WithBuildArgs(args []corev1.EnvVar) Scheduler - WithEnvs(envs []corev1.EnvVar) Scheduler - Schedule() (*api.ContainerBuild, error) -} - -type Reconciler interface { - WithClient(client client.Client) Reconciler - CancelBuild() (*api.ContainerBuild, error) - Reconcile() (*api.ContainerBuild, error) -} - -type MountHandler interface { - // AddResource the actual file/resource to add to the build context in the relative root path. Might be called multiple times. - AddResource(target string, content []byte) MountHandler - // AddConfigMapResource the configMap to add to the build context. Might be called multiple times. - // This ConfigMap is a Kubernetes LocalObjectReference, meaning that must be within the Platform namespace. - AddConfigMapResource(configMap corev1.LocalObjectReference, path string) MountHandler - WithClient(client client.Client) MountHandler - Scheduler() Scheduler -} - -type schedulerManager interface { - CreateScheduler(info ContainerBuilderInfo, ctx *containerBuildContext, hook schedulerHook) Scheduler - CanHandle(info ContainerBuilderInfo) bool -} - -// NewBuild is the API entry for the Reconciler. Create a new ContainerBuild instance based on PlatformContainerBuild. -func NewBuild(info ContainerBuilderInfo) MountHandler { - buildContext := &containerBuildContext{ - baseImage: info.Platform.Spec.BaseImage, - ctx: context.TODO(), - } - return &mountHandler{ - containerBuildContext: buildContext, - reconciler: &reconciler{containerBuildContext: buildContext}, - info: info, - resources: make([]resource, 0), - resourceConfigMaps: make([]resourceConfigMap, 0), - } -} - -func (m *mountHandler) newContainerBuild() (*api.ContainerBuild, error) { - // TODO: create a handler to mount the resources according to the platform/context options, for now only CM - if err := mountResourcesBinaryWithConfigMapToBuild(m.containerBuildContext, &m.resources); err != nil { - return nil, err - } - // Add the CMs to the build volume - mountResourcesConfigMapToBuild(m.containerBuildContext, &m.resourceConfigMaps) - return m.reconciler.Reconcile() -} - -func (m *mountHandler) WithClient(client client.Client) MountHandler { - m.containerBuildContext.c = client - return m -} - -func (m *mountHandler) AddResource(target string, content []byte) MountHandler { - m.resources = append(m.resources, resource{target, content, ""}) - return m -} - -func (m *mountHandler) AddConfigMapResource(configMap corev1.LocalObjectReference, path string) MountHandler { - m.resourceConfigMaps = append(m.resourceConfigMaps, resourceConfigMap{configMap, path}) - return m -} - -func (m *mountHandler) Scheduler() Scheduler { - for _, v := range schedulers { - if v.CanHandle(m.info) { - return v.CreateScheduler(m.info, m.containerBuildContext, m.newContainerBuild) - } - } - panic(fmt.Errorf("ContainerBuildStrategy %s with PublishStrategy %s is not supported", - m.info.Platform.Spec.BuildStrategy, - m.info.Platform.Spec.PublishStrategy)) -} - -func FromBuild(build *api.ContainerBuild) Reconciler { - return &reconciler{ - containerBuildContext: &containerBuildContext{ - containerBuild: build, - ctx: context.TODO(), - }, - } -} - -func (b *reconciler) WithClient(client client.Client) Reconciler { - b.containerBuildContext.c = client - return b -} - -// Reconcile idempotent build flow control. -// Can be called many times to check/update the current status of the build instance, indexed by the Platform and ContainerBuild Name. -func (b *reconciler) Reconcile() (*api.ContainerBuild, error) { - var actions []Action - switch b.containerBuildContext.containerBuild.Spec.Strategy { - case api.ContainerBuildStrategyPod: - // build the action flow: - actions = []Action{ - newInitializePodAction(), - newScheduleAction(), - newMonitorPodAction(), - newErrorRecoveryAction(), - } - } - - target := b.containerBuildContext.containerBuild.DeepCopy() - - for _, a := range actions { - a.InjectClient(b.containerBuildContext.c) - - if a.CanHandle(target) { - klog.V(log.I).InfoS("Invoking action", "buildAction", a.Name()) - newTarget, err := a.Handle(b.containerBuildContext.ctx, target) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to invoke action", "buildAction", a.Name()) - return nil, err - } - - if newTarget != nil { - if newTarget.Status.Phase != target.Status.Phase { - klog.V(log.I).InfoS( - "state transition", - "phase-from", target.Status.Phase, - "phase-to", newTarget.Status.Phase, - ) - } - - target = newTarget - } - break - } - } - - return target, nil -} - -func (b *reconciler) CancelBuild() (*api.ContainerBuild, error) { - // TODO: do the actual implementation if that makes sense - panic("CancelBuild: Operation Not Supported") -} diff --git a/container-builder/builder/kubernetes/builder_kaniko.go b/container-builder/builder/kubernetes/builder_kaniko.go deleted file mode 100644 index 57216515..00000000 --- a/container-builder/builder/kubernetes/builder_kaniko.go +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "path" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -var _ Scheduler = &kanikoScheduler{} - -type kanikoScheduler struct { - schedulerHook schedulerHook - kanikoTask *api.KanikoTask - info ContainerBuilderInfo - containerBuildContext *containerBuildContext -} - -type kanikoSchedulerManager struct { -} - -var _ schedulerManager = &kanikoSchedulerManager{} - -func (k kanikoSchedulerManager) CreateScheduler(info ContainerBuilderInfo, ctx *containerBuildContext, hook schedulerHook) Scheduler { - kanikoTask := api.KanikoTask{ - ContainerBuildBaseTask: api.ContainerBuildBaseTask{Name: "KanikoTask"}, - PublishTask: api.PublishTask{ - ContextDir: path.Join("/builder", info.BuildUniqueName, "context"), - BaseImage: info.Platform.Spec.BaseImage, - Image: info.FinalImageName, - Registry: info.Platform.Spec.Registry, - }, - Cache: api.KanikoTaskCache{}, - KanikoExecutorImage: info.ContainerBuilderImageTag, - } - - ctx.containerBuild = &api.ContainerBuild{ - Spec: api.ContainerBuildSpec{ - Tasks: []api.ContainerBuildTask{{Kaniko: &kanikoTask}}, - Strategy: api.ContainerBuildStrategyPod, - Timeout: *info.Platform.Spec.Timeout, - }, - Status: api.ContainerBuildStatus{}, - } - ctx.containerBuild.Name = info.BuildUniqueName - ctx.containerBuild.Namespace = info.Platform.Namespace - - sched := &kanikoScheduler{ - schedulerHook: hook, - kanikoTask: &kanikoTask, - } - return sched -} - -func (k kanikoSchedulerManager) CanHandle(info ContainerBuilderInfo) bool { - return info.Platform.Spec.BuildStrategy == api.ContainerBuildStrategyPod && info.Platform.Spec.PublishStrategy == api.PlatformBuildPublishStrategyKaniko -} - -func (sk *kanikoScheduler) WithProperty(property BuilderProperty, object interface{}) Scheduler { - if property == KanikoCache { - sk.kanikoTask.Cache = object.(api.KanikoTaskCache) - } - return sk -} - -func (sk *kanikoScheduler) WithResourceRequirements(res corev1.ResourceRequirements) Scheduler { - sk.kanikoTask.Resources = res - return sk -} - -func (sk *kanikoScheduler) WithAdditionalArgs(flags []string) Scheduler { - sk.kanikoTask.AdditionalFlags = flags - return sk -} - -func (sk *kanikoScheduler) WithBuildArgs(args []corev1.EnvVar) Scheduler { - sk.kanikoTask.BuildArgs = args - return sk -} - -func (sk *kanikoScheduler) WithEnvs(envs []corev1.EnvVar) Scheduler { - sk.kanikoTask.Envs = envs - return sk -} - -func (sk *kanikoScheduler) Schedule() (*api.ContainerBuild, error) { - return sk.schedulerHook() -} diff --git a/container-builder/builder/kubernetes/builder_kaniko_test.go b/container-builder/builder/kubernetes/builder_kaniko_test.go deleted file mode 100644 index 9f8173d2..00000000 --- a/container-builder/builder/kubernetes/builder_kaniko_test.go +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "os" - "testing" - "time" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - resource2 "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/util" - "github.com/kubesmarts/logic-operator/container-builder/util/test" -) - -// Test that verify we are able to create a Kaniko build with cache enabled, a specific set of resources and additional flags -func TestNewBuildWithKanikoCustomizations(t *testing.T) { - ns := "test" - c := test.NewFakeClient() - - dockerFile, err := os.ReadFile("testdata/sample.Dockerfile") - assert.NoError(t, err) - - workflowDefinition, err := os.ReadFile("testdata/greetings.sw.json") - assert.NoError(t, err) - - platform := api.PlatformContainerBuild{ - ObjectReference: api.ObjectReference{ - Namespace: ns, - Name: "testPlatform", - }, - Spec: api.PlatformContainerBuildSpec{ - BuildStrategy: api.ContainerBuildStrategyPod, - PublishStrategy: api.PlatformBuildPublishStrategyKaniko, - Timeout: &metav1.Duration{Duration: 5 * time.Minute}, - }, - } - - // Sample CPU and Memory quantities - cpuQty, _ := resource2.ParseQuantity("1") - memQty, _ := resource2.ParseQuantity("1Gi") - - // Sample additional flag - addFlags := make([]string, 1) - addFlags[0] = "--use-new-run=true" - - // create the new build, schedule with cache enabled, a specific set of resources and additional flags - build, err := NewBuild(ContainerBuilderInfo{FinalImageName: "host/namespace/myservice:latest", BuildUniqueName: "build1", Platform: platform}). - AddResource("Dockerfile", dockerFile). - AddResource("greetings.sw.json", workflowDefinition). - WithClient(c). - Scheduler(). - WithProperty(KanikoCache, api.KanikoTaskCache{Enabled: util.Pbool(true), PersistentVolumeClaim: "kaniko-cache-pv"}). - WithResourceRequirements(v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceCPU: cpuQty, - v1.ResourceMemory: memQty, - }, - Requests: v1.ResourceList{ - v1.ResourceCPU: cpuQty, - v1.ResourceMemory: memQty, - }, - }). - WithAdditionalArgs(addFlags). - Schedule() - - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhaseScheduling, build.Status.Phase) - - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhasePending, build.Status.Phase) - - // The status won't change since FakeClient won't set the status upon creation, since we don't have a controller :) - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhasePending, build.Status.Phase) - - podName := buildPodName(build) - pod := &v1.Pod{} - err = c.Get(context.TODO(), types.NamespacedName{Name: podName, Namespace: ns}, pod) - assert.NoError(t, err) - assert.NotNil(t, pod) - assert.Len(t, pod.Spec.Volumes, 1) - - assert.Subset(t, pod.Spec.Containers[0].Args, addFlags) -} - -func TestNewBuildWithKanikoWithBuildArgsAndEnv(t *testing.T) { - ns := "test" - c := test.NewFakeClient() - - dockerFile, err := os.ReadFile("testdata/sample.Dockerfile") - assert.NoError(t, err) - - workflowDefinition, err := os.ReadFile("testdata/greetings.sw.json") - assert.NoError(t, err) - - platform := api.PlatformContainerBuild{ - ObjectReference: api.ObjectReference{ - Namespace: ns, - Name: "testPlatform", - }, - Spec: api.PlatformContainerBuildSpec{ - BuildStrategy: api.ContainerBuildStrategyPod, - PublishStrategy: api.PlatformBuildPublishStrategyKaniko, - Timeout: &metav1.Duration{Duration: 5 * time.Minute}, - }, - } - - build, err := NewBuild(ContainerBuilderInfo{FinalImageName: "host/namespace/service:latest", BuildUniqueName: "build1", Platform: platform}). - AddResource("Dockerfile", dockerFile). - AddResource("greetings.sw.json", workflowDefinition). - WithClient(c). - Scheduler(). - WithBuildArgs([]v1.EnvVar{{ - Name: "QUARKUS_EXTENSIONS", - Value: "extension1,extension2", - }, { - Name: "MY_PROPERTY", - Value: "my_property_value", - }}). - WithEnvs([]v1.EnvVar{{ - Name: "MYENV", - Value: "value", - }}). - Schedule() - assert.NoError(t, err) - - // reconcile twice to push forward to the pod creation - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - - podName := buildPodName(build) - pod := &v1.Pod{} - err = c.Get(context.TODO(), types.NamespacedName{Name: podName, Namespace: ns}, pod) - assert.NoError(t, err) - assert.NotNil(t, pod) - - assert.Subset(t, pod.Spec.Containers[0].Args, []string{"--build-arg=QUARKUS_EXTENSIONS=extension1,extension2"}) - assert.Subset(t, pod.Spec.Containers[0].Args, []string{"--build-arg=MY_PROPERTY=my_property_value"}) - assert.Subset(t, pod.Spec.Containers[0].Env, []v1.EnvVar{{Name: "MYENV", Value: "value"}}) -} diff --git a/container-builder/builder/kubernetes/builder_test.go b/container-builder/builder/kubernetes/builder_test.go deleted file mode 100644 index 7f4567bf..00000000 --- a/container-builder/builder/kubernetes/builder_test.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "os" - "testing" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/util/test" -) - -func TestNewBuild(t *testing.T) { - ns := "test" - c := test.NewFakeClient() - - dockerFile, err := os.ReadFile("testdata/sample.Dockerfile") - assert.NoError(t, err) - - workflowDefinition, err := os.ReadFile("testdata/greetings.sw.json") - assert.NoError(t, err) - - platform := api.PlatformContainerBuild{ - ObjectReference: api.ObjectReference{ - Namespace: ns, - Name: "testPlatform", - }, - Spec: api.PlatformContainerBuildSpec{ - BuildStrategy: api.ContainerBuildStrategyPod, - PublishStrategy: api.PlatformBuildPublishStrategyKaniko, - Timeout: &metav1.Duration{Duration: 5 * time.Minute}, - }, - } - // create the new build, schedule - build, err := NewBuild(ContainerBuilderInfo{FinalImageName: "host/namespace/myservice:latest", BuildUniqueName: "build1", Platform: platform}). - WithClient(c). - AddResource("Dockerfile", dockerFile). - AddResource("greetings.sw.json", workflowDefinition). - Scheduler().Schedule() - - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhaseScheduling, build.Status.Phase) - - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhasePending, build.Status.Phase) - - // The status won't change since FakeClient won't set the status upon creation, since we don't have a controller :) - build, err = FromBuild(build).WithClient(c).Reconcile() - assert.NoError(t, err) - assert.NotNil(t, build) - assert.Equal(t, api.ContainerBuildPhasePending, build.Status.Phase) - - podName := buildPodName(build) - pod := &v1.Pod{} - err = c.Get(context.TODO(), types.NamespacedName{Name: podName, Namespace: ns}, pod) - assert.NoError(t, err) - assert.NotNil(t, pod) - assert.Len(t, pod.Spec.Volumes, 1) -} diff --git a/container-builder/builder/kubernetes/env.go b/container-builder/builder/kubernetes/env.go deleted file mode 100644 index f71f5b71..00000000 --- a/container-builder/builder/kubernetes/env.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "fmt" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -// FromEnvToArgs converts an EnvVar array into an args string slice. E.g. name=value,name=value -func FromEnvToArgs(c client.Client, ns string, envVars ...v1.EnvVar) ([]string, error) { - args := make([]string, 0) - for _, env := range envVars { - if env.ValueFrom == nil { - args = append(args, fmt.Sprintf("%s=%s", env.Name, env.Value)) - } else { - if env.ValueFrom.ConfigMapKeyRef != nil { - cm := &v1.ConfigMap{} - if err := c.Get(context.TODO(), types.NamespacedName{Name: env.ValueFrom.ConfigMapKeyRef.Name, Namespace: ns}, cm); err != nil { - t := true - if errors.IsNotFound(err) && env.ValueFrom.ConfigMapKeyRef.Optional == &t { - continue - } - return nil, err - } - args = append(args, fmt.Sprintf("%s=%s", env.Name, cm.Data[env.ValueFrom.ConfigMapKeyRef.Key])) - continue - } - if env.ValueFrom.SecretKeyRef != nil { - secret := &v1.Secret{} - if err := c.Get(context.TODO(), types.NamespacedName{Name: env.ValueFrom.SecretKeyRef.Name, Namespace: ns}, secret); err != nil { - t := true - if errors.IsNotFound(err) && env.ValueFrom.SecretKeyRef.Optional == &t { - continue - } - return nil, err - } - args = append(args, fmt.Sprintf("%s=%s", env.Name, secret.Data[env.ValueFrom.SecretKeyRef.Key])) - continue - } - return nil, fmt.Errorf("can't convert to args the env var %s on namespace %s. Only Secrets and ConfigMaps are supported", env.Name, ns) - } - } - return args, nil -} diff --git a/container-builder/builder/kubernetes/error.go b/container-builder/builder/kubernetes/error.go deleted file mode 100644 index b9927828..00000000 --- a/container-builder/builder/kubernetes/error.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -func newErrorAction() Action { - return &errorAction{} -} - -type errorAction struct { - baseAction -} - -// Name returns a common name of the action. -func (action *errorAction) Name() string { - return "error" -} - -// CanHandle tells whether this action can handle the build. -func (action *errorAction) CanHandle(build *api.ContainerBuild) bool { - return build.Status.Phase == api.ContainerBuildPhaseError -} - -// Handle handles the builds. -func (action *errorAction) Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) { - return nil, nil -} diff --git a/container-builder/builder/kubernetes/initialize_pod.go b/container-builder/builder/kubernetes/initialize_pod.go deleted file mode 100644 index 6fadf3a1..00000000 --- a/container-builder/builder/kubernetes/initialize_pod.go +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - - "github.com/pkg/errors" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -func newInitializePodAction() Action { - return &initializePodAction{} -} - -type initializePodAction struct { - baseAction -} - -// Name returns a common name of the action. -func (action *initializePodAction) Name() string { - return "initialize-pod" -} - -// CanHandle tells whether this action can handle the build. -func (action *initializePodAction) CanHandle(build *api.ContainerBuild) bool { - return build.Status.Phase == "" || build.Status.Phase == api.ContainerBuildPhaseInitialization -} - -// Handle handles the builds. -func (action *initializePodAction) Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) { - if err := deleteBuilderPod(ctx, action.client, build); err != nil { - return nil, errors.Wrap(err, "cannot delete build pod") - } - - pod, err := getBuilderPod(ctx, action.client, build) - if err != nil || pod != nil { - // We return and wait for the pod to be deleted before de-queue the build pod. - return nil, err - } - - build.Status.Phase = api.ContainerBuildPhaseScheduling - - return build, nil -} diff --git a/container-builder/builder/kubernetes/kaniko.go b/container-builder/builder/kubernetes/kaniko.go deleted file mode 100644 index 192a98ca..00000000 --- a/container-builder/builder/kubernetes/kaniko.go +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "fmt" - "strings" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/container-builder/util/minikube" - "github.com/kubesmarts/logic-operator/container-builder/util/registry" -) - -var ( - gcrKanikoRegistrySecret = registrySecret{ - fileName: "kaniko-secret.json", - mountPath: "/secret", - destination: "kaniko-secret.json", - refEnv: "GOOGLE_APPLICATION_CREDENTIALS", - } - plainDockerKanikoRegistrySecret = registrySecret{ - fileName: "config.json", - mountPath: "/kaniko/.docker", - destination: "config.json", - } - standardDockerKanikoRegistrySecret = registrySecret{ - fileName: corev1.DockerConfigJsonKey, - mountPath: "/kaniko/.docker", - destination: "config.json", - } - - kanikoRegistrySecrets = []registrySecret{ - gcrKanikoRegistrySecret, - plainDockerKanikoRegistrySecret, - standardDockerKanikoRegistrySecret, - } -) - -// see: https://github.com/GoogleContainerTools/kaniko#flag---build-arg -const kanikoBuildArgs = "--build-arg" - -func addKanikoTaskToPod(ctx context.Context, c client.Client, build *api.ContainerBuild, task *api.KanikoTask, pod *corev1.Pod) error { - // TODO: perform an actual registry lookup based on the environment - if task.Registry.Address == "" { - address, err := registry.GetRegistryAddress(ctx, c) - if err != nil { - return err - } - if address != nil { - task.Registry.Address = *address - } else { - address, err = minikube.FindRegistry(ctx, c) - if err != nil { - return err - } - if address != nil { - task.Registry.Address = *address - } - } - } - - // TODO: verify how cache is possible - // TODO: the PlatformContainerBuild structure should be able to identify the Kaniko context. For simplicity, let's use a CM with `dir://` - args := []string{ - "--dockerfile=Dockerfile", - "--context=dir://" + task.ContextDir, - "--destination=" + task.GetRepositoryImageTag(), - "--ignore-path=/product_uuid", - } - - if task.AdditionalFlags != nil && len(task.AdditionalFlags) > 0 { - args = append(args, task.AdditionalFlags...) - } - - if task.Verbose != nil && *task.Verbose { - args = append(args, "-v=debug") - } - - affinity := &corev1.Affinity{} - env := make([]corev1.EnvVar, 0) - env = append(env, task.Envs...) - volumes := make([]corev1.Volume, 0) - volumeMounts := make([]corev1.VolumeMount, 0) - - if task.Registry.Secret != "" { - secret, err := getRegistrySecret(ctx, c, pod.Namespace, task.Registry.Secret, kanikoRegistrySecrets) - if err != nil { - return err - } - addRegistrySecret(task.Registry.Secret, secret, &volumes, &volumeMounts, &env) - } - - if task.Registry.Insecure { - args = append(args, "--insecure") - args = append(args, "--insecure-pull") - } - - // TODO: should be handled by a mount build context handler instead since we can have many possibilities - if err := addResourcesToBuilderContextVolume(ctx, c, task.PublishTask, build, &volumes, &volumeMounts); err != nil { - return err - } - - env = append(env, proxyFromEnvironment()...) - - buildArgs, err := FromEnvToArgs(c, pod.Namespace, task.BuildArgs...) - if err != nil { - return err - } - if len(buildArgs) > 0 { - for _, buildArg := range buildArgs { - args = append(args, fmt.Sprintf("%s=%s", kanikoBuildArgs, buildArg)) - } - } - - container := corev1.Container{ - Name: strings.ToLower(task.Name), - Image: task.KanikoExecutorImage, - ImagePullPolicy: corev1.PullIfNotPresent, - Args: args, - Env: env, - WorkingDir: task.ContextDir, - VolumeMounts: volumeMounts, - Resources: task.Resources, - //SecurityContext: KanikoSecurityDefaults(), - } - - // We may want to handle possible conflicts - pod.Spec.Affinity = affinity - pod.Spec.Volumes = append(pod.Spec.Volumes, volumes...) - pod.Spec.Containers = append(pod.Spec.Containers, container) - - return nil -} diff --git a/container-builder/builder/kubernetes/kanikoSecurityContext.go b/container-builder/builder/kubernetes/kanikoSecurityContext.go deleted file mode 100644 index 1de4e325..00000000 --- a/container-builder/builder/kubernetes/kanikoSecurityContext.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/container-builder/util" -) - -func KanikoSecurityDefaults() *corev1.SecurityContext { - return &corev1.SecurityContext{ - AllowPrivilegeEscalation: util.Pbool(false), - Privileged: util.Pbool(false), - RunAsNonRoot: util.Pbool(true), - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - Capabilities: &corev1.Capabilities{ - Drop: []corev1.Capability{corev1.Capability("ALL")}, - }, - } -} diff --git a/container-builder/builder/kubernetes/monitor_pod.go b/container-builder/builder/kubernetes/monitor_pod.go deleted file mode 100644 index 9e0822e5..00000000 --- a/container-builder/builder/kubernetes/monitor_pod.go +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "encoding/json" - "os" - "time" - - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/tools/remotecommand" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -const timeoutAnnotation = "sonataflow.org/timeout" - -func newMonitorPodAction() Action { - return &monitorPodAction{} -} - -type monitorPodAction struct { - baseAction -} - -// Name returns a common name of the action. -func (action *monitorPodAction) Name() string { - return "monitor-pod" -} - -// CanHandle tells whether this action can handle the build. -func (action *monitorPodAction) CanHandle(build *api.ContainerBuild) bool { - return build.Status.Phase == api.ContainerBuildPhasePending || build.Status.Phase == api.ContainerBuildPhaseRunning -} - -func (action *monitorPodAction) Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) { - pod, err := getBuilderPod(ctx, action.client, build) - if err != nil { - return nil, err - } - - if pod == nil { - switch build.Status.Phase { - - case api.ContainerBuildPhasePending: - if pod, err = newBuildPod(ctx, action.client, build); err != nil { - return nil, err - } - // TODO: every object we create, must pass to a listener for our client code. For example, an operator would like to add their labels/owner refs - - if err = action.client.Create(ctx, pod); err != nil { - return nil, errors.Wrap(err, "cannot create build pod") - } - - case api.ContainerBuildPhaseRunning: - // Emulate context cancellation - build.Status.Phase = api.ContainerBuildPhaseInterrupted - build.Status.Error = "Pod deleted" - return build, nil - } - } - - switch pod.Status.Phase { - - case corev1.PodPending, corev1.PodRunning: - // Pod remains in pending phase when init containers execute - if action.isPodScheduled(pod) { - build.Status.Phase = api.ContainerBuildPhaseRunning - } - if time.Since(build.Status.StartedAt.Time) > build.Spec.Timeout.Duration { - // Patch the Pod with an annotation, to identify termination signal - // has been sent because the ContainerBuild has timed out - if err = action.addTimeoutAnnotation(ctx, pod, metav1.Now()); err != nil { - return nil, err - } - } - - case corev1.PodSucceeded: - build.Status.Phase = api.ContainerBuildPhaseSucceeded - // Remove the annotation in case the ContainerBuild succeeded, between - // the timeout deadline and the termination signal. - if err = action.removeTimeoutAnnotation(ctx, pod); err != nil { - return nil, err - } - finishedAt := action.getTerminatedTime(pod) - duration := finishedAt.Sub(build.Status.StartedAt.Time) - build.Status.Duration = duration.String() - - for _, task := range build.Spec.Tasks { - if t := task.Kaniko; t != nil { - build.Status.RepositoryImageTag = t.GetRepositoryImageTag() - break - } - } - - case corev1.PodFailed: - phase := api.ContainerBuildPhaseFailed - message := "Pod failed" - if terminationMessage := action.getTerminationMessage(pod); terminationMessage != "" { - message = terminationMessage - } - if pod.DeletionTimestamp != nil { - phase = api.ContainerBuildPhaseInterrupted - message = "Pod deleted" - } else if _, ok := pod.GetAnnotations()[timeoutAnnotation]; ok { - message = "ContainerBuild timeout" - } - // Do not override errored build - if build.Status.Phase == api.ContainerBuildPhaseError { - phase = api.ContainerBuildPhaseError - } - build.Status.Phase = phase - build.Status.Error = message - finishedAt := action.getTerminatedTime(pod) - duration := finishedAt.Sub(build.Status.StartedAt.Time) - build.Status.Duration = duration.String() - } - - return build, nil -} - -func (action *monitorPodAction) sigterm(pod *corev1.Pod) error { - var containers []corev1.ContainerStatus - containers = append(containers, pod.Status.InitContainerStatuses...) - containers = append(containers, pod.Status.ContainerStatuses...) - - for _, container := range containers { - if container.State.Running == nil { - continue - } - - r := action.client.CoreV1().RESTClient().Post(). - Resource("pods"). - Namespace(pod.Namespace). - Name(pod.Name). - SubResource("exec"). - Param("container", container.Name) - - r.VersionedParams(&corev1.PodExecOptions{ - Container: container.Name, - Command: []string{"kill", "-SIGTERM", "1"}, - Stdout: true, - Stderr: true, - TTY: false, - }, scheme.ParameterCodec) - - exec, err := remotecommand.NewSPDYExecutor(action.client.GetConfig(), "POST", r.URL()) - if err != nil { - return err - } - - err = exec.Stream(remotecommand.StreamOptions{ - Stdout: os.Stdout, - Stderr: os.Stderr, - Tty: false, - }) - if err != nil { - return err - } - } - - return nil -} - -func (action *monitorPodAction) isPodScheduled(pod *corev1.Pod) bool { - for _, condition := range pod.Status.Conditions { - if condition.Type == corev1.PodScheduled && condition.Status == corev1.ConditionTrue { - return true - } - } - return false -} - -func (action *monitorPodAction) addTimeoutAnnotation(ctx context.Context, pod *corev1.Pod, time metav1.Time) error { - if _, ok := pod.GetAnnotations()[timeoutAnnotation]; ok { - return nil - } - return action.patchPod(ctx, pod, func(p *corev1.Pod) { - if p.GetAnnotations() != nil { - p.GetAnnotations()[timeoutAnnotation] = time.String() - } else { - p.SetAnnotations(map[string]string{ - timeoutAnnotation: time.String(), - }) - } - }) -} - -func (action *monitorPodAction) removeTimeoutAnnotation(ctx context.Context, pod *corev1.Pod) error { - if _, ok := pod.GetAnnotations()[timeoutAnnotation]; !ok { - return nil - } - return action.patchPod(ctx, pod, func(p *corev1.Pod) { - delete(p.GetAnnotations(), timeoutAnnotation) - }) -} - -func (action *monitorPodAction) patchPod(ctx context.Context, pod *corev1.Pod, mutate func(*corev1.Pod)) error { - target := pod.DeepCopy() - mutate(target) - if err := action.client.Patch(ctx, target, ctrl.MergeFrom(pod)); err != nil { - return err - } - *pod = *target - return nil -} - -func (action *monitorPodAction) getTerminatedTime(pod *corev1.Pod) metav1.Time { - var finishedAt metav1.Time - - var containers []corev1.ContainerStatus - containers = append(containers, pod.Status.InitContainerStatuses...) - containers = append(containers, pod.Status.ContainerStatuses...) - - for _, container := range containers { - if container.State.Terminated == nil { - // The container has not run - continue - } - if t := container.State.Terminated.FinishedAt; finishedAt.IsZero() || t.After(finishedAt.Time) { - finishedAt = t - } - } - - return finishedAt -} - -func (action *monitorPodAction) getTerminationMessage(pod *corev1.Pod) string { - var terminationMessages []terminationMessage - - var containers []corev1.ContainerStatus - containers = append(containers, pod.Status.InitContainerStatuses...) - containers = append(containers, pod.Status.ContainerStatuses...) - - for _, container := range containers { - if t := container.State.Terminated; t != nil && t.ExitCode != 0 && t.Message != "" { - terminationMessages = append(terminationMessages, terminationMessage{ - Container: container.Name, - Message: t.Message, - }) - } - } - - switch len(terminationMessages) { - case 0: - return "" - case 1: - return terminationMessages[0].Message - default: - message, err := json.Marshal(terminationMessages) - if err != nil { - return "" - } - return string(message) - } -} - -type terminationMessage struct { - Container string `json:"container,omitempty"` - Message string `json:"message,omitempty"` -} diff --git a/container-builder/builder/kubernetes/mount.go b/container-builder/builder/kubernetes/mount.go deleted file mode 100644 index f54f39ab..00000000 --- a/container-builder/builder/kubernetes/mount.go +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "fmt" - "path" - - "github.com/google/uuid" - "github.com/pkg/errors" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -type configMapVolumeBuildContext struct { - VolumeMount []corev1.VolumeMount - Volume corev1.Volume -} - -// addResourcesToBuilderContextVolume add the build resources to volumes. Usually these volumes are added to a build pod. The resources reference must be previously created. -func addResourcesToBuilderContextVolume(ctx context.Context, client client.Client, task api.PublishTask, build *api.ContainerBuild, volumes *[]corev1.Volume, volumeMounts *[]corev1.VolumeMount) error { - // TODO: do it via specialized handlers, since we might have multiple volumeMounts types (configMap, Secrets, AWS, GCP, etc). - // TODO: for now, what we have is a context based on CMs so one projected volume for everything is enough and easier to setup. - // See https://kubernetes.io/docs/concepts/storage/projected-volumes/ - mounts := make(map[string]configMapVolumeBuildContext, 0) - - for _, resVol := range build.Status.ResourceVolumes { - switch resVol.ReferenceType { - case api.ResourceReferenceTypeConfigMap: - configMap := &corev1.ConfigMap{} - err := client.Get(ctx, types.NamespacedName{Name: resVol.ReferenceName, Namespace: build.Namespace}, configMap) - if err != nil { - klog.ErrorS(err, "Failed to fetch configMap to add to build context", "configMap", resVol.ReferenceName, "Namespace", build.Namespace) - return err - } - entry, ok := mounts[resVol.DestinationDir] - var volName string - if ok { - volName = entry.Volume.Name - } else { - volName = uuid.NewString() - mounts[resVol.DestinationDir] = configMapVolumeBuildContext{ - Volume: corev1.Volume{ - Name: volName, - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{}, - }, - }, - } - entry = mounts[resVol.DestinationDir] - } - - cmMounts := make([]corev1.VolumeMount, len(configMap.Data)) - i := 0 - for fileName := range configMap.Data { - cmMounts[i] = corev1.VolumeMount{ - Name: volName, - MountPath: path.Join(task.ContextDir, resVol.DestinationDir, fileName), - SubPath: fileName, - ReadOnly: true, - } - i++ - } - entry.VolumeMount = append(entry.VolumeMount, cmMounts...) - entry.Volume.Projected.Sources = append(entry.Volume.Projected.Sources, corev1.VolumeProjection{ - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{Name: configMap.Name}, - }, - }) - mounts[resVol.DestinationDir] = entry - default: - return errors.Errorf("unsupported resource mount type for build %s on ns %s", build.Name, build.Namespace) - } - } - - for _, cmMount := range mounts { - *volumeMounts = append(*volumeMounts, cmMount.VolumeMount...) - *volumes = append(*volumes, cmMount.Volume) - } - - return nil -} - -// Mount the given ConfigMaps to the ContainerBuild that later will be mounted in the build context. -func mountResourcesConfigMapToBuild(buildContext *containerBuildContext, cms *[]resourceConfigMap) { - if cms == nil || len(*cms) == 0 { - return - } - for _, cm := range *cms { - buildContext.containerBuild.Status.ResourceVolumes = append(buildContext.containerBuild.Status.ResourceVolumes, api.ContainerBuildResourceVolume{ - ReferenceName: cm.Ref.Name, - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: cm.Path, - }) - } -} - -// Mount the given resource(s) files in a ConfigMap and then add it to the ContainerBuild that later will be mounted in the build context -func mountResourcesBinaryWithConfigMapToBuild(buildContext *containerBuildContext, resources *[]resource) error { - if resources == nil || len(*resources) == 0 { - return nil - } - configMap, err := getOrCreateResourcesBinaryConfigMap(buildContext, resources) - if err != nil { - return err - } - - buildContext.containerBuild.Status.ResourceVolumes = append(buildContext.containerBuild.Status.ResourceVolumes, api.ContainerBuildResourceVolume{ - ReferenceName: configMap.Name, - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: "", - }) - - return nil -} - -func getResourcesBinaryConfigMap(c context.Context, client client.Client, build *api.ContainerBuild) (*corev1.ConfigMap, error) { - resourcesConfigMap := corev1.ConfigMap{} - configMapId := types.NamespacedName{Name: buildPodName(build), Namespace: build.Namespace} - - if err := client.Get(c, configMapId, &resourcesConfigMap); err != nil { - if k8serrors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - - return &resourcesConfigMap, nil -} - -func getOrCreateResourcesBinaryConfigMap(buildContext *containerBuildContext, resources *[]resource) (*corev1.ConfigMap, error) { - // TODO: build an actual configMap builder context handler - resourcesConfigMap, err := getResourcesBinaryConfigMap(buildContext.ctx, buildContext.c, buildContext.containerBuild) - if err != nil { - return nil, err - } - - if resourcesConfigMap == nil { - resourcesConfigMap = &corev1.ConfigMap{} - configMapId := types.NamespacedName{Name: buildPodName(buildContext.containerBuild), Namespace: buildContext.containerBuild.Namespace} - resourcesConfigMap.Namespace = configMapId.Namespace - resourcesConfigMap.Name = configMapId.Name - addBinaryContentToConfigMap(resourcesConfigMap, resources) - // TODO: every object we create, must pass to a listener for our client code. For example, an operator would like to add their labels/owner refs - if err := buildContext.c.Create(buildContext.ctx, resourcesConfigMap); err != nil { - return nil, err - } - } else { - addBinaryContentToConfigMap(resourcesConfigMap, resources) - if err := buildContext.c.Update(buildContext.ctx, resourcesConfigMap); err != nil { - return nil, err - } - } - - return resourcesConfigMap, nil -} - -func addBinaryContentToConfigMap(configMap *corev1.ConfigMap, resources *[]resource) { - configMap.BinaryData = make(map[string][]byte) - configMap.Data = make(map[string]string) - for _, resource := range *resources { - configMap.Data[resource.Target] = fmt.Sprintf("%s", resource.Content) - } -} diff --git a/container-builder/builder/kubernetes/mount_test.go b/container-builder/builder/kubernetes/mount_test.go deleted file mode 100644 index 4f5b3959..00000000 --- a/container-builder/builder/kubernetes/mount_test.go +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/util/test" -) - -func Test_addResourcesToBuilderContextVolume_specificPath(t *testing.T) { - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cm-data", - Namespace: t.Name(), - }, - Data: map[string]string{ - "specfile.json": "{}", - }, - } - task := api.PublishTask{ - ContextDir: "/build/context", - } - build := &api.ContainerBuild{ - ObjectReference: api.ObjectReference{ - Name: "build", - Namespace: t.Name(), - }, - Status: api.ContainerBuildStatus{ - ResourceVolumes: []api.ContainerBuildResourceVolume{ - { - ReferenceName: "cm-data", - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: "specs", - }, - }, - }, - } - volumes := make([]corev1.Volume, 0) - volumeMounts := make([]corev1.VolumeMount, 0) - client := test.NewFakeClient(cm) - - err := addResourcesToBuilderContextVolume(context.TODO(), client, task, build, &volumes, &volumeMounts) - assert.NoError(t, err) - - assert.Len(t, volumes, 1) - assert.Len(t, volumeMounts, 1) - assert.Contains(t, volumeMounts[0].MountPath, task.ContextDir) - assert.Len(t, volumes[0].Projected.Sources, 1) -} - -func Test_addResourcesToBuilderContextVolume_rootPath(t *testing.T) { - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cm-data", - Namespace: t.Name(), - }, - Data: map[string]string{ - "workflow.sw.json": "{}", - "Dockerfike": "FROM:RHEL", - }, - } - task := api.PublishTask{ - ContextDir: "/build/context", - } - build := &api.ContainerBuild{ - ObjectReference: api.ObjectReference{ - Name: "build", - Namespace: t.Name(), - }, - Status: api.ContainerBuildStatus{ - ResourceVolumes: []api.ContainerBuildResourceVolume{ - { - ReferenceName: "cm-data", - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: "", - }, - }, - }, - } - volumes := make([]corev1.Volume, 0) - volumeMounts := make([]corev1.VolumeMount, 0) - client := test.NewFakeClient(cm) - - err := addResourcesToBuilderContextVolume(context.TODO(), client, task, build, &volumes, &volumeMounts) - assert.NoError(t, err) - - assert.Len(t, volumes, 1) - // one for each file within the CM - assert.Len(t, volumeMounts, 2) - assert.Contains(t, volumeMounts[0].MountPath, task.ContextDir) - assert.Contains(t, volumeMounts[1].MountPath, task.ContextDir) - assert.Len(t, volumes[0].Projected.Sources, 1) -} - -func Test_addResourcesToBuilderContextVolume_multipleCMs(t *testing.T) { - cm1 := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cm-data1", - Namespace: t.Name(), - }, - Data: map[string]string{ - "workflow.sw.json": "{}", - "Dockerfike": "FROM:RHEL", - }, - } - cm2 := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cm-data2", - Namespace: t.Name(), - }, - Data: map[string]string{ - "openapi.json": "{}", - }, - } - task := api.PublishTask{ - ContextDir: "/build/context", - } - build := &api.ContainerBuild{ - ObjectReference: api.ObjectReference{ - Name: "build", - Namespace: t.Name(), - }, - Status: api.ContainerBuildStatus{ - ResourceVolumes: []api.ContainerBuildResourceVolume{ - { - ReferenceName: "cm-data1", - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: "", - }, - { - ReferenceName: "cm-data2", - ReferenceType: api.ResourceReferenceTypeConfigMap, - DestinationDir: "specs", - }, - }, - }, - } - volumes := make([]corev1.Volume, 0) - volumeMounts := make([]corev1.VolumeMount, 0) - client := test.NewFakeClient(cm1, cm2) - - err := addResourcesToBuilderContextVolume(context.TODO(), client, task, build, &volumes, &volumeMounts) - assert.NoError(t, err) - - assert.Len(t, volumes, 2) - // one for each file within the CM - assert.Len(t, volumeMounts, 3) - assert.Contains(t, volumeMounts[0].MountPath, task.ContextDir) - assert.Contains(t, volumeMounts[1].MountPath, task.ContextDir) - assert.Contains(t, volumeMounts[2].MountPath, task.ContextDir) - // Two projections in different dirs - assert.Len(t, volumes[0].Projected.Sources, 1) - assert.Len(t, volumes[1].Projected.Sources, 1) -} diff --git a/container-builder/builder/kubernetes/recovery.go b/container-builder/builder/kubernetes/recovery.go deleted file mode 100644 index 58306969..00000000 --- a/container-builder/builder/kubernetes/recovery.go +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "time" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" - - "github.com/jpillora/backoff" - - "github.com/kubesmarts/logic-operator/container-builder/api" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func newErrorRecoveryAction() Action { - // TODO: externalize options - return &errorRecoveryAction{ - backOff: backoff.Backoff{ - Min: 5 * time.Second, - Max: 1 * time.Minute, - Factor: 2, - Jitter: false, - }, - } -} - -type errorRecoveryAction struct { - baseAction - backOff backoff.Backoff -} - -func (action *errorRecoveryAction) Name() string { - return "error-recovery" -} - -func (action *errorRecoveryAction) CanHandle(build *api.ContainerBuild) bool { - return build.Status.Phase == api.ContainerBuildPhaseFailed -} - -func (action *errorRecoveryAction) Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) { - if build.Status.Failure == nil { - build.Status.Failure = &api.ContainerBuildFailure{ - Reason: build.Status.Error, - Time: metav1.Now(), - Recovery: api.ContainerBuildFailureRecovery{ - Attempt: 0, - AttemptMax: 5, - }, - } - return build, nil - } - - if build.Status.Failure.Recovery.Attempt >= build.Status.Failure.Recovery.AttemptMax { - build.Status.Phase = api.ContainerBuildPhaseError - return build, nil - } - - lastAttempt := build.Status.Failure.Recovery.AttemptTime.Time - if lastAttempt.IsZero() { - lastAttempt = build.Status.Failure.Time.Time - } - - elapsed := time.Since(lastAttempt).Seconds() - elapsedMin := action.backOff.ForAttempt(float64(build.Status.Failure.Recovery.Attempt)).Seconds() - - if elapsed < elapsedMin { - return nil, nil - } - - build.Status.Phase = api.ContainerBuildPhaseInitialization - build.Status.Failure.Recovery.Attempt++ - build.Status.Failure.Recovery.AttemptTime = metav1.Now() - - klog.V(log.I).InfoS("Recovery attempt", - "attempt", build.Status.Failure.Recovery.Attempt, - "attemptMax", build.Status.Failure.Recovery.AttemptMax, - ) - - return build, nil -} diff --git a/container-builder/builder/kubernetes/schedule.go b/container-builder/builder/kubernetes/schedule.go deleted file mode 100644 index a80b29d2..00000000 --- a/container-builder/builder/kubernetes/schedule.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" -) - -func newScheduleAction() Action { - return &scheduleAction{} -} - -type scheduleAction struct { - baseAction -} - -// Name returns a common name of the action. -func (action *scheduleAction) Name() string { - return "schedule" -} - -// CanHandle tells whether this action can handle the build. -func (action *scheduleAction) CanHandle(build *api.ContainerBuild) bool { - return build.Status.Phase == api.ContainerBuildPhaseScheduling -} - -// Handle handles the builds. -func (action *scheduleAction) Handle(ctx context.Context, build *api.ContainerBuild) (*api.ContainerBuild, error) { - // TODO do any work required between initialization and scheduling, like enqueueing builds - now := metav1.Now() - build.Status.StartedAt = &now - build.Status.Phase = api.ContainerBuildPhasePending - - return build, nil -} diff --git a/container-builder/builder/kubernetes/testdata/greetings.sw.json b/container-builder/builder/kubernetes/testdata/greetings.sw.json deleted file mode 100644 index a619b3b8..00000000 --- a/container-builder/builder/kubernetes/testdata/greetings.sw.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "id": "jsongreet", - "version": "1.0", - "name": "Greeting workflow", - "description": "JSON based greeting workflow", - "start": "ChooseOnLanguage", - "functions": [ - { - "name": "greetFunction", - "type": "custom", - "operation": "sysout" - } - ], - "states": [ - { - "name": "ChooseOnLanguage", - "type": "switch", - "dataConditions": [ - { - "condition": "${ .language == \"English\" }", - "transition": "GreetInEnglish" - }, - { - "condition": "${ .language == \"Spanish\" }", - "transition": "GreetInSpanish" - } - ], - "defaultCondition": { - "transition": "GreetInEnglish" - } - }, - { - "name": "GreetInEnglish", - "type": "inject", - "data": { - "greeting": "Hello from JSON Workflow, " - }, - "transition": "GreetPerson" - }, - { - "name": "GreetInSpanish", - "type": "inject", - "data": { - "greeting": "Saludos desde JSON Workflow, " - }, - "transition": "GreetPerson" - }, - { - "name": "GreetPerson", - "type": "operation", - "actions": [ - { - "name": "greetAction", - "functionRef": { - "refName": "greetFunction", - "arguments": { - "message": ".greeting+.name" - } - } - } - ], - "end": { - "terminate": true - } - } - ] -} diff --git a/container-builder/builder/kubernetes/testdata/sample.Dockerfile b/container-builder/builder/kubernetes/testdata/sample.Dockerfile deleted file mode 100644 index 63307297..00000000 --- a/container-builder/builder/kubernetes/testdata/sample.Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Sample Dockerfile used in tests -FROM ubuntu:20.04 - -# Set environment variables -ENV DEBIAN_FRONTEND=noninteractive - -# Update and install necessary dependencies -RUN apt-get update && apt-get install -y \ - curl \ - git \ - python3 \ - python3-pip \ - build-essential \ - && rm -rf /var/lib/apt/lists/* - -# Install Python dependencies (if needed) -COPY requirements.txt /app/requirements.txt -RUN pip3 install -r /app/requirements.txt - -# Set up working directory -WORKDIR /app - -# Copy project files into the container -COPY . /app - -# Expose any ports (if your application needs it) -EXPOSE 8080 - -# Command to run the application or test -CMD ["python3", "app.py"] diff --git a/container-builder/cleaner/cleaner.go b/container-builder/cleaner/cleaner.go deleted file mode 100644 index 8dfb4e69..00000000 --- a/container-builder/cleaner/cleaner.go +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 cleaner - -type RegistryCleaner interface { - RemoveImagesUntagged() (bool, error) - RemoveDanglingImages() (bool, error) - PurgeImages() (bool, error) - RemoveImagesFiltered(repo string, tag string) (bool, error) -} diff --git a/container-builder/cleaner/docker_integration_test.go b/container-builder/cleaner/docker_integration_test.go deleted file mode 100644 index f37c4348..00000000 --- a/container-builder/cleaner/docker_integration_test.go +++ /dev/null @@ -1,67 +0,0 @@ -//go:build integration_docker - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 cleaner - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/common" - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -const ( - testImg = "busybox" - latestTag = "latest" - testImgLocalTag = "localhost:5000/busybox:latest" -) - -func TestDockerIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(DockerTestSuite)) -} - -func (suite *DockerTestSuite) TestImagesOperationsOnDockerRegistryForTest() { - pullErr := suite.Docker.PullImage(testImg + ":" + latestTag) - if pullErr != nil { - klog.V(log.E).ErrorS(pullErr, "Pull Error") - } - assert.Nil(suite.T(), pullErr, "Pull image failed") - time.Sleep(2 * time.Second) // Needed on CI - assert.True(suite.T(), suite.LocalRegistry.IsImagePresent(testImg), "Test image not found in the registry after the pull") - tagErr := suite.Docker.TagImage(testImg, testImgLocalTag) - if tagErr != nil { - klog.V(log.E).ErrorS(tagErr, "Tag Error") - } - - assert.Nil(suite.T(), tagErr, "Tag image failed") - time.Sleep(2 * time.Second) // Needed on CI - pushErr := suite.Docker.PushImage(testImgLocalTag, common.RegistryContainerUrlFromDockerSocket, "", "") - if pushErr != nil { - klog.V(log.E).ErrorS(pushErr, "Push Error") - } - - assert.Nil(suite.T(), pushErr, "Push image in the Docker container failed") -} diff --git a/container-builder/cleaner/docker_integration_test_suite.go b/container-builder/cleaner/docker_integration_test_suite.go deleted file mode 100644 index 0e22f06c..00000000 --- a/container-builder/cleaner/docker_integration_test_suite.go +++ /dev/null @@ -1,63 +0,0 @@ -//go:build integration_docker - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 cleaner - -import ( - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/common" - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -type DockerTestSuite struct { - suite.Suite - LocalRegistry common.DockerLocalRegistry - RegistryID string - Docker common.Docker -} - -func (suite *DockerTestSuite) SetupSuite() { - dockerRegistryContainer, registryID, docker := common.SetupDockerSocket() - if len(registryID) > 0 { - suite.LocalRegistry = dockerRegistryContainer - suite.RegistryID = registryID - suite.Docker = docker - } else { - assert.FailNow(suite.T(), "Initialization failed %s", registryID) - } -} - -func (suite *DockerTestSuite) TearDownSuite() { - registryID := suite.LocalRegistry.GetRegistryRunningID() - if len(registryID) > 0 { - common.DockerTearDown(suite.LocalRegistry) - } else { - suite.LocalRegistry.StopRegistry() - } - purged, err := suite.Docker.PurgeContainer("", common.RegistryImg) - if err != nil { - klog.V(log.E).ErrorS(err, "Error during purged container in TearDown Suite.") - } - klog.V(log.I).InfoS("Purged container", "containers", purged) -} diff --git a/container-builder/cleaner/registry_docker_integration_test.go b/container-builder/cleaner/registry_docker_integration_test.go deleted file mode 100644 index 86d8a8cd..00000000 --- a/container-builder/cleaner/registry_docker_integration_test.go +++ /dev/null @@ -1,44 +0,0 @@ -//go:build integration_docker - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 cleaner - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -func TestRegistryDockerIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(DockerTestSuite)) -} - -func (suite *DockerTestSuite) TestDockerRegistry() { - klog.V(log.I).InfoS("TestPullTagPush ") - assert.Truef(suite.T(), suite.RegistryID != "", "Registry not started") - assert.Truef(suite.T(), suite.LocalRegistry.IsRegistryImagePresent(), "Registry image not present") - assert.Truef(suite.T(), suite.LocalRegistry.GetRegistryRunningID() == suite.RegistryID, "Registry container not running") - assert.True(suite.T(), suite.LocalRegistry.Connection.DaemonHost() == "unix:///var/run/docker.sock") -} diff --git a/container-builder/client/client.go b/container-builder/client/client.go deleted file mode 100644 index 24450f41..00000000 --- a/container-builder/client/client.go +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 client - -import ( - "os" - "path/filepath" - - "k8s.io/klog/v2" - - user "github.com/mitchellh/go-homedir" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/config" - "sigs.k8s.io/controller-runtime/pkg/manager" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -const ( - inContainerNamespaceFile = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" - kubeConfigEnvVar = "KUBECONFIG" -) - -// Client is an abstraction for a k8s client. -type Client interface { - ctrl.Client - kubernetes.Interface - GetScheme() *runtime.Scheme - GetConfig() *rest.Config -} - -// Injectable identifies objects that can receive a Client. -type Injectable interface { - InjectClient(Client) -} - -// Provider is used to provide a new instance of the Client each time it's required. -type Provider struct { - Get func() (Client, error) -} - -type defaultClient struct { - ctrl.Client - kubernetes.Interface - scheme *runtime.Scheme - config *rest.Config -} - -// Check interface compliance. -var _ Client = &defaultClient{} - -func (c *defaultClient) GetScheme() *runtime.Scheme { - return c.scheme -} - -func (c *defaultClient) GetConfig() *rest.Config { - return c.config -} - -// NewOutOfClusterClient creates a new k8s client that can be used from outside the cluster. -func NewOutOfClusterClient(kubeconfig string) (Client, error) { - initialize(kubeconfig) - // using fast discovery from outside the cluster - return NewClient(true) -} - -// NewClient creates a new k8s client that can be used from outside or in the cluster. -func NewClient(fastDiscovery bool) (Client, error) { - cfg, err := config.GetConfig() - if err != nil { - return nil, err - } - return NewClientWithConfig(fastDiscovery, cfg) -} - -// NewClientWithConfig creates a new k8s client that can be used from outside or in the cluster. -func NewClientWithConfig(fastDiscovery bool, cfg *rest.Config) (Client, error) { - clientScheme := scheme.Scheme - - var err error - var clientset kubernetes.Interface - if clientset, err = kubernetes.NewForConfig(cfg); err != nil { - return nil, err - } - - var mapper meta.RESTMapper - if fastDiscovery { - mapper = newFastDiscoveryRESTMapper(cfg) - } - - // Create a new client to avoid using cache (enabled by default with controller-runtime client) - clientOptions := ctrl.Options{ - Scheme: clientScheme, - Mapper: mapper, - } - dynClient, err := ctrl.New(cfg, clientOptions) - if err != nil { - return nil, err - } - - return &defaultClient{ - Client: dynClient, - Interface: clientset, - scheme: clientOptions.Scheme, - config: cfg, - }, nil -} - -// FromManager creates a new k8s client from a manager object. -func FromManager(manager manager.Manager) (Client, error) { - var err error - var clientset kubernetes.Interface - if clientset, err = kubernetes.NewForConfig(manager.GetConfig()); err != nil { - return nil, err - } - - return &defaultClient{ - Client: manager.GetClient(), - Interface: clientset, - scheme: manager.GetScheme(), - config: manager.GetConfig(), - }, nil -} - -// FromCtrlClientSchemeAndConfig create client from a kubernetes controller client, a scheme and a configuration. -func FromCtrlClientSchemeAndConfig(client ctrl.Client, scheme *runtime.Scheme, conf *rest.Config) (Client, error) { - var err error - var clientset kubernetes.Interface - if clientset, err = kubernetes.NewForConfig(conf); err != nil { - return nil, err - } - - return &defaultClient{ - Client: client, - Interface: clientset, - scheme: scheme, - config: conf, - }, nil -} - -// init initialize the k8s client for usage outside the cluster. -func initialize(kubeconfig string) { - if kubeconfig == "" { - // skip out-of-cluster initialization if inside the container - if kc, err := shouldUseContainerMode(); kc && err == nil { - return - } else if err != nil { - klog.V(log.E).ErrorS(err, "could not determine if running in a container") - } - var err error - kubeconfig, err = getDefaultKubeConfigFile() - if err != nil { - panic(err) - } - } - - if err := os.Setenv(kubeConfigEnvVar, kubeconfig); err != nil { - panic(err) - } -} - -func getDefaultKubeConfigFile() (string, error) { - dir, err := user.Dir() - if err != nil { - return "", err - } - - return filepath.Join(dir, ".kube", "config"), nil -} - -func shouldUseContainerMode() (bool, error) { - // When kube config is set, container mode is not used - if os.Getenv(kubeConfigEnvVar) != "" { - return false, nil - } - // Use container mode only when the kubeConfigFile does not exist and the container namespace file is present - configFile, err := getDefaultKubeConfigFile() - if err != nil { - return false, err - } - configFilePresent := true - _, err = os.Stat(configFile) - if err != nil && os.IsNotExist(err) { - configFilePresent = false - } else if err != nil { - return false, err - } - if !configFilePresent { - _, err := os.Stat(inContainerNamespaceFile) - if os.IsNotExist(err) { - return false, nil - } - return true, err - } - return false, nil -} - -func getNamespaceFromKubernetesContainer() (string, error) { - var nsba []byte - var err error - if nsba, err = os.ReadFile(inContainerNamespaceFile); err != nil { - return "", err - } - return string(nsba), nil -} diff --git a/container-builder/client/fastmapper.go b/container-builder/client/fastmapper.go deleted file mode 100644 index 7c82ed06..00000000 --- a/container-builder/client/fastmapper.go +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 client - -import ( - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/discovery" - "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" - "k8s.io/klog/v2" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -// FastMapperAllowedAPIGroups contains a set of API groups that are allowed when using the fastmapper. -// Those must correspond to all groups used by the "kamel" binary tool when running out-of-cluster. -var FastMapperAllowedAPIGroups = map[string]bool{ - "": true, // core APIs - "apiextensions.k8s.io": true, - "apps": true, - "batch": true, - "rbac.authorization.k8s.io": true, - "console.openshift.io": true, // OpenShift console resources - "operators.coreos.com": true, // Operator SDK OLM - "monitoring.coreos.com": true, // Prometheus resources -} - -// newFastDiscoveryRESTMapper comes from https://github.com/kubernetes-sigs/controller-runtime/pull/592. -// We may leverage the controller-runtime bits in the future, if that gets merged upstream. -func newFastDiscoveryRESTMapper(config *rest.Config) meta.RESTMapper { - return meta.NewLazyRESTMapperLoader(func() (meta.RESTMapper, error) { - return newFastDiscoveryRESTMapperWithFilter(config, func(g *metav1.APIGroup) bool { - return FastMapperAllowedAPIGroups[g.Name] - }) - }) -} - -func newFastDiscoveryRESTMapperWithFilter(config *rest.Config, filter func(*metav1.APIGroup) bool) (meta.RESTMapper, error) { - dc := discovery.NewDiscoveryClientForConfigOrDie(config) - groups, err := dc.ServerGroups() - if err != nil { - return nil, err - } - wg := wait.Group{} - totalCount := 0 - pickedCount := 0 - grs := make([]*restmapper.APIGroupResources, 0) - for _, group := range groups.Groups { - pinnedGroup := group - pick := filter(&pinnedGroup) - klog.V(log.D).InfoS("Group", "name", pick) - totalCount++ - if !pick { - continue - } - pickedCount++ - gr := &restmapper.APIGroupResources{ - Group: group, - VersionedResources: make(map[string][]metav1.APIResource), - } - grs = append(grs, gr) - wg.Start(func() { discoverGroupResources(dc, gr) }) - } - wg.Wait() - klog.V(log.D).InfoS("Picked", "pickedCount", pickedCount, "totalCount", totalCount) - return restmapper.NewDiscoveryRESTMapper(grs), nil -} - -func discoverGroupResources(dc discovery.DiscoveryInterface, gr *restmapper.APIGroupResources) { - for _, version := range gr.Group.Versions { - resources, err := dc.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - klog.V(log.E).ErrorS(err, version.GroupVersion) - } - gr.VersionedResources[version.Version] = resources.APIResources - } -} diff --git a/container-builder/common/docker.go b/container-builder/common/docker.go deleted file mode 100644 index f2a945c5..00000000 --- a/container-builder/common/docker.go +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "encoding/base64" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/registry" - - "k8s.io/klog/v2" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - - "github.com/kubesmarts/logic-operator/container-builder/util" - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -type Docker struct { - Connection *client.Client -} - -// https://docs.docker.com/engine/api/latest/ -func (d Docker) GetClient() (*client.Client, error) { - return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) -} - -func (d Docker) GetClientRemoteFromEnv(host string) (*client.Client, error) { - return client.NewClientWithOpts(client.FromEnv, client.WithHost(host)) -} - -func (d Docker) GetClientRemote(host string, cacertPath string, certPath string, keyPath string) (*client.Client, error) { - return client.NewClientWithOpts(client.WithHost(host), client.WithAPIVersionNegotiation(), client.WithTLSClientConfig(cacertPath, certPath, keyPath)) -} - -func (d Docker) GetImages(args types.ImageListOptions) ([]types.ImageSummary, error) { - images, err := d.Connection.ImageList(context.Background(), args) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Get Images") - return nil, err - } - return images, nil -} - -// RemoveImagesUntagged removes the images with tag : -func (d Docker) RemoveImagesUntagged() (bool, error) { - images, err := d.GetImages(types.ImageListOptions{All: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Images Untagged") - return false, err - } - for _, image := range images { - if image.RepoTags != nil && image.RepoTags[0] == ":" && image.RepoDigests[0] == "@" { - item, err := d.Connection.ImageRemove(context.Background(), image.ID, types.ImageRemoveOptions{PruneChildren: true, Force: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Images Untagged", "item", item) - return false, err - } - } - } - return true, nil -} - -// RemoveDanglingImages removes the images with the filter dangling true -func (d Docker) RemoveDanglingImages() (bool, error) { - filters := filters.NewArgs() - filters.Add("dangling", "true") - images, err := d.GetImages(types.ImageListOptions{Filters: filters}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Dangling Images") - return false, err - } - for _, image := range images { - item, err := d.Connection.ImageRemove(context.Background(), image.ID, types.ImageRemoveOptions{PruneChildren: true, Force: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Dangling Images", "item", item) - return false, err - } - } - return true, nil -} - -// Purge images with dangling true -func (d Docker) PurgeImages() (bool, error) { - filters := filters.NewArgs() - filters.Add("dangling", "true") - report, err := d.Connection.ImagesPrune(context.Background(), filters) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Purge Images") - return false, err - } else { - klog.V(log.I).InfoS("Images purged", "images", report.ImagesDeleted) - return true, nil - } -} - -func (d Docker) PurgeContainer(id string, image string) (bool, error) { - containers, err := d.Connection.ContainerList(context.Background(), types.ContainerListOptions{All: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Purge Container") - return false, err - } else { - for _, container := range containers { - if container.Image == image || container.ID == id { - d.ContainerKill(container.ID) - d.ContainerRemove(container.ID) - klog.V(log.I).InfoS("Purged container", "ID", container.ID) - } - } - return true, nil - } -} - -// remove all the images found using the repo name, with or without tag -func (d Docker) RemoveImagesFiltered(repo string, tag string) (bool, error) { - filters := filters.NewArgs() - if len(repo) > 0 && len(tag) > 0 { - filters.Add("reference", repo+":"+tag) - } - if len(repo) > 0 { - filters.Add("reference", repo) - } - - images, err := d.GetImages(types.ImageListOptions{Filters: filters}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Images Filtered") - return false, err - } - for _, image := range images { - item, err := d.Connection.ImageRemove(context.Background(), image.ID, types.ImageRemoveOptions{PruneChildren: true, Force: true}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Remove Images Filtered", "item", item) - return false, err - } - } - return true, nil -} - -func (d Docker) TagImage(imageSource string, imageTag string) error { - err := d.Connection.ImageTag(context.Background(), imageSource, imageTag) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Tag Image") - } - return err -} - -func (d Docker) PushImage(image string, url string, username string, password string) error { - var authConfig = registry.AuthConfig{ - Username: username, - Password: password, - ServerAddress: url, - } - authConfigBytes, _ := json.Marshal(authConfig) - authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes) - - opts := types.ImagePushOptions{RegistryAuth: authConfigEncoded} - resp, err := d.Connection.ImagePush(context.Background(), image, opts) - if err != nil { - body, _ := ioutil.ReadAll(resp) - klog.V(log.E).ErrorS(err, "error during Push Image", "body", body) - } - return err -} - -func (d Docker) PullImage(image string) error { - _, err := d.Connection.ImagePull(context.Background(), image, types.ImagePullOptions{}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Pull Image") - } - return err -} - -func (d Docker) GetContainerID(imageName string) (string, error) { - containers, err := d.Connection.ContainerList(context.Background(), types.ContainerListOptions{}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Get Container ID") - } - - for _, container := range containers { - if container.Image == imageName { - return container.ID, nil - } - } - return "", nil -} - -func (d Docker) ContainerStop(containerID string) error { - stopOptions := container.StopOptions{ - Timeout: util.Pint(10), - } - err := d.Connection.ContainerStop(context.Background(), containerID, stopOptions) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Container Stop") - } - return err -} - -func (d Docker) ContainerKill(containerID string) error { - err := d.Connection.ContainerKill(context.Background(), containerID, "SIGKILL") - if err != nil { - klog.V(log.E).ErrorS(err, "error during Container Kill") - } - return err -} - -func (d Docker) ContainerRemove(containerID string) error { - err := d.Connection.ContainerRemove(context.Background(), containerID, types.ContainerRemoveOptions{}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Container Remove") - } - return err -} diff --git a/container-builder/common/registry.go b/container-builder/common/registry.go deleted file mode 100644 index e8938380..00000000 --- a/container-builder/common/registry.go +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - "net" - "os" - - "github.com/docker/docker/client" -) - -const ( - RegistryContainerUrlFromDockerSocket = "tcp://localhost:5000" - RegistryImg = "registry" - registryImgFullTag = "docker.io/library/registry:latest" -) - -type DockerLocalRegistry struct { - Connection *client.Client -} - -func IsPortAvailable(port string) bool { - ln, err := net.Listen("tcp", ":"+port) - defer ln.Close() - if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Can't listen on port %q: %s", port, err) - return false - } - return true -} diff --git a/container-builder/common/registry_docker.go b/container-builder/common/registry_docker.go deleted file mode 100644 index 58c38c70..00000000 --- a/container-builder/common/registry_docker.go +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - "strings" - "time" - - "k8s.io/klog/v2" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" - "golang.org/x/net/context" - - "github.com/kubesmarts/logic-operator/container-builder/util/log" -) - -func GetDockerConnection() (*client.Client, error) { - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - fmt.Println(err) - return nil, err - } - return cli, nil -} - -func (d DockerLocalRegistry) getConnection() (*client.Client, error) { - connectionLocal := d.Connection - if connectionLocal == nil { - return GetDockerConnection() - } - return connectionLocal, nil -} - -func (d DockerLocalRegistry) StartRegistry() string { - //wait until Podman registry shutdown in the podman tests - for { - time.Sleep(1 * time.Second) - if IsPortAvailable("5000") { - break - } - } - - ctx := context.Background() - registryID := d.GetRegistryRunningID() - - if len(registryID) > 0 { - klog.V(log.I).InfoS("Registry ID is already running", "ID", registryID) - return registryID - } - - if !d.IsRegistryImagePresent() { - klog.V(log.I).InfoS("Registry Image Pull") - _, err := d.Connection.ImagePull(ctx, RegistryImg, types.ImagePullOptions{}) - if err != nil { - fmt.Println(err) - return "" - } - } - - time.Sleep(2 * time.Second) // needed on CI - - klog.V(log.I).InfoS("Registry Container Create") - resp, err := d.Connection.ContainerCreate(ctx, &container.Config{ - Image: RegistryImg, - ExposedPorts: nat.PortSet{"5000": struct{}{}}, - }, - &container.HostConfig{ - PortBindings: map[nat.Port][]nat.PortBinding{nat.Port("5000"): {{HostIP: "127.0.0.1", HostPort: "5000"}}}, - }, - nil, - nil, - RegistryImg) - - if err != nil { - klog.V(log.E).ErrorS(err, "error during Registry Container Create") - } - - klog.V(log.I).InfoS("Starting Registry Container") - if err := d.Connection.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { - klog.V(log.E).ErrorS(err, "error during Start Registry Container") - return "" - } - - // give some time to start - klog.V(log.I).InfoS("Waiting 4 seconds") - time.Sleep(4 * time.Second) - return d.GetRegistryRunningID() -} - -func (d DockerLocalRegistry) StopRegistry() bool { - registryID := d.GetRegistryRunningID() - if len(registryID) > 0 { - klog.V(log.I).InfoS("StopRegistry Kill Container", "ID", registryID) - ctx := context.Background() - _ = d.Connection.ContainerKill(ctx, registryID, "SIGKILL") - klog.V(log.I).InfoS("StopRegistry Removing Container", "ID", registryID) - err := d.Connection.ContainerRemove(ctx, registryID, types.ContainerRemoveOptions{}) - if err != nil { - klog.V(log.E).ErrorS(err, "error during Stop Registry") - return false - } - } - return true -} - -func (d DockerLocalRegistry) StopAndRemoveContainer(containerID string) bool { - if len(containerID) > 0 { - ctx := context.Background() - klog.V(log.I).InfoS("Docker StopAndRemoveContainer Kill registry container", "ID", containerID) - _ = d.Connection.ContainerKill(ctx, containerID, "SIGKILL") - klog.V(log.I).InfoS("Docker StopAndRemoveContainer Removing container", "ID", containerID) - err := d.Connection.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{}) - return err == nil - } - fmt.Println("Docker StopAndRemoveContainer Invalid ID " + containerID) - return true -} - -func (d DockerLocalRegistry) GetRegistryRunningID() string { - containers, err := d.Connection.ContainerList(context.Background(), types.ContainerListOptions{}) - if err != nil { - fmt.Println(err) - return "" - } - - for _, container := range containers { - if container.Image == RegistryImg { - return container.ID - } - } - return "" -} - -func (d DockerLocalRegistry) IsRegistryImagePresent() bool { - - imageList, err := d.Connection.ImageList(context.Background(), types.ImageListOptions{}) - if err != nil { - return false - } - for _, imagex := range imageList { - if (len(imagex.RepoTags) > 0 && imagex.RepoTags[0] == RegistryImg) || (len(imagex.RepoDigests) > 0 && strings.HasPrefix(imagex.RepoDigests[0], RegistryImg)) { - return true - } - } - return false -} - -func (d DockerLocalRegistry) IsImagePresent(name string) bool { - - imageList, err := d.Connection.ImageList(context.Background(), types.ImageListOptions{}) - if err != nil { - return false - } - for _, imagex := range imageList { - if len(imagex.RepoTags) == 0 || len(imagex.RepoDigests) == 0 { - continue - } - if imagex.RepoTags[0] == name || (imagex.RepoDigests != nil && strings.HasPrefix(imagex.RepoDigests[0], name)) { - return true - } - } - return false -} - -func SetupDockerSocket() (DockerLocalRegistry, string, Docker) { - dockerSocketConn, err := GetDockerConnection() - - if err != nil { - klog.V(log.E).ErrorS(err, "Can't get Docker socket") - return DockerLocalRegistry{}, "", Docker{} - } - dockerSock := Docker{Connection: dockerSocketConn} - - if err != nil { - klog.V(log.E).ErrorS(err, "error during SetupDockerSocket") - } - _, err = dockerSock.PurgeContainer("", RegistryImg) - if err != nil { - klog.V(log.E).ErrorS(err, "error during SetupDockerSocket") - } - - d := DockerLocalRegistry{Connection: dockerSocketConn} - klog.V(log.I).InfoS("Check if registry image is present", "isPresent", d.IsRegistryImagePresent()) - if !d.IsRegistryImagePresent() { - dockerSock.PullImage(registryImgFullTag) - } - registryID := d.GetRegistryRunningID() - if len(registryID) == 0 { - registryID = d.StartRegistry() - klog.V(log.I).InfoS("Registry started") - } else { - klog.V(log.I).InfoS("Registry already up and running", "ID", registryID) - } - return d, registryID, dockerSock - -} - -func DockerTearDown(dlr DockerLocalRegistry) { - if len(dlr.GetRegistryRunningID()) > 0 { - registryID := dlr.GetRegistryRunningID() - dlr.StopAndRemoveContainer(registryID) - } else { - dlr.StopRegistry() - } -} diff --git a/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml b/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml deleted file mode 100644 index 2ae6a50b..00000000 --- a/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: build-kaniko-using-cache-and-customizations -spec: - tasks: - - kaniko: - resources: - requests: - memory: "1Gi" - cpu: "1" - limits: - memory: "2Gi" - cpu: "2" - additionalFlags: - - "--use-new-run=true" - - "--cache=true" - - "--cache-dir=/kaniko/cache" diff --git a/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml b/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml deleted file mode 100644 index 81ae3ff6..00000000 --- a/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: platform-kaniko-using-cache -spec: - publishStrategy: "Kaniko" - baseImage: host/namespace/image:latest - registry: - address: host/namespace - secret: regcred - PublishStrategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/container-builder/examples/app.yaml b/container-builder/examples/app.yaml deleted file mode 100644 index babd5c1b..00000000 --- a/container-builder/examples/app.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# example deployment that can be used to run the built image -apiVersion: apps/v1 -kind: Deployment -metadata: - name: sonataflow-greetings - labels: - app: sonataflow-greetings -spec: - replicas: 1 - selector: - matchLabels: - app: sonataflow-greetings - template: - metadata: - labels: - app: sonataflow-greetings - spec: - containers: - - name: sonataflow-greetings - # taken from kaniko logs - image: 10.107.131.33/greetings:latest - ports: - - containerPort: 8080 - env: - - name: QUARKUS_LAUNCH_DEVMODE - value: "true" - - name: QUARKUS_KOGITO_DEVSERVICES_ENABLED - value: "false" diff --git a/container-builder/examples/dockerfiles/SonataFlow.dockerfile b/container-builder/examples/dockerfiles/SonataFlow.dockerfile deleted file mode 100644 index 82d94abe..00000000 --- a/container-builder/examples/dockerfiles/SonataFlow.dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -FROM docker.io/apache/incubator-kie-sonataflow-builder:main AS builder - -# Kogito User -USER 1001 - -ARG QUARKUS_PACKAGE_TYPE="jar" -ARG SCRIPT_DEBUG="false" - - # Copy from build context to skeleton resources project -COPY * ./resources/ - -RUN /home/kogito/launch/build-app.sh ./resources -#============================= -# Runtime Run -#============================= -FROM registry.access.redhat.com/ubi9/openjdk-17-runtime:latest - -ARG QUARKUS_LAUNCH_DEVMODE=false - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/lib/ /deployments/lib/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/*.jar /deployments/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/app/ /deployments/app/ -COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 185 -ENV AB_JOLOKIA_OFF="" -ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/container-builder/examples/service.yaml b/container-builder/examples/service.yaml deleted file mode 100644 index c9702464..00000000 --- a/container-builder/examples/service.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: Service -apiVersion: v1 -metadata: - name: sonataflow-greetings-external - labels: - app: sonataflow-greetings -spec: - ports: - - protocol: TCP - port: 8080 - targetPort: 8080 - nodePort: 31961 - selector: - app: sonataflow-greetings - type: NodePort - sessionAffinity: None - externalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - allocateLoadBalancerNodePorts: true - internalTrafficPolicy: Cluster diff --git a/container-builder/examples/sources/sonataflowgreetings.sw.json b/container-builder/examples/sources/sonataflowgreetings.sw.json deleted file mode 100644 index a619b3b8..00000000 --- a/container-builder/examples/sources/sonataflowgreetings.sw.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "id": "jsongreet", - "version": "1.0", - "name": "Greeting workflow", - "description": "JSON based greeting workflow", - "start": "ChooseOnLanguage", - "functions": [ - { - "name": "greetFunction", - "type": "custom", - "operation": "sysout" - } - ], - "states": [ - { - "name": "ChooseOnLanguage", - "type": "switch", - "dataConditions": [ - { - "condition": "${ .language == \"English\" }", - "transition": "GreetInEnglish" - }, - { - "condition": "${ .language == \"Spanish\" }", - "transition": "GreetInSpanish" - } - ], - "defaultCondition": { - "transition": "GreetInEnglish" - } - }, - { - "name": "GreetInEnglish", - "type": "inject", - "data": { - "greeting": "Hello from JSON Workflow, " - }, - "transition": "GreetPerson" - }, - { - "name": "GreetInSpanish", - "type": "inject", - "data": { - "greeting": "Saludos desde JSON Workflow, " - }, - "transition": "GreetPerson" - }, - { - "name": "GreetPerson", - "type": "operation", - "actions": [ - { - "name": "greetAction", - "functionRef": { - "refName": "greetFunction", - "arguments": { - "message": ".greeting+.name" - } - } - } - ], - "end": { - "terminate": true - } - } - ] -} diff --git a/container-builder/go.mod b/container-builder/go.mod deleted file mode 100644 index 26d49919..00000000 --- a/container-builder/go.mod +++ /dev/null @@ -1,98 +0,0 @@ -module github.com/kubesmarts/logic-operator/container-builder - -go 1.26.0 - -require ( - github.com/docker/docker v28.5.2+incompatible - github.com/docker/go-connections v0.5.0 - github.com/google/uuid v1.6.0 - github.com/jpillora/backoff v1.0.0 - github.com/mitchellh/go-homedir v1.1.0 - github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.9.0 - golang.org/x/net v0.47.0 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/client-go v0.31.1 - k8s.io/klog/v2 v2.130.1 - sigs.k8s.io/controller-runtime v0.19.0 -) - -require ( - github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/errdefs v1.0.0 // indirect - github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/spdystream v0.4.0 // indirect - github.com/moby/sys/atomicwriter v0.1.0 // indirect - github.com/moby/term v0.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/x448/float16 v0.8.4 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.38.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - gotest.tools/v3 v3.5.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) diff --git a/container-builder/go.sum b/container-builder/go.sum deleted file mode 100644 index cc9c8c2a..00000000 --- a/container-builder/go.sum +++ /dev/null @@ -1,278 +0,0 @@ -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= -github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/container-builder/hack/boilerplate.go.txt b/container-builder/hack/boilerplate.go.txt deleted file mode 100644 index 72209755..00000000 --- a/container-builder/hack/boilerplate.go.txt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ \ No newline at end of file diff --git a/container-builder/hack/btrfs_installed_tag.sh b/container-builder/hack/btrfs_installed_tag.sh deleted file mode 100755 index 0073717f..00000000 --- a/container-builder/hack/btrfs_installed_tag.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -${CPP:-${CC:-cc} -E} ${CPPFLAGS} - > /dev/null 2> /dev/null << EOF -#include -EOF -if test $? -ne 0 ; then - echo exclude_graphdriver_btrfs -fi diff --git a/container-builder/hack/btrfs_tag.sh b/container-builder/hack/btrfs_tag.sh deleted file mode 100755 index 479fee3c..00000000 --- a/container-builder/hack/btrfs_tag.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -${CPP:-${CC:-cc} -E} ${CPPFLAGS} - > /dev/null 2> /dev/null << EOF -#include -EOF -if test $? -ne 0 ; then - echo btrfs_noversion -fi diff --git a/container-builder/main.go b/container-builder/main.go deleted file mode 100644 index 85f6ceac..00000000 --- a/container-builder/main.go +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 main - -import ( - "fmt" - "os" - "time" - - builder "github.com/kubesmarts/logic-operator/container-builder/builder/kubernetes" - - v1 "k8s.io/api/core/v1" - resource2 "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -/* -Usage example. Please note that you must have a valid Kubernetes environment up and running. -*/ - -func main() { - cli, err := client.NewOutOfClusterClient("") - - dockerFile, err := os.ReadFile("examples/dockerfiles/SonataFlow.dockerfile") - if err != nil { - panic("Can't read dockerfile") - } - source, err := os.ReadFile("examples/sources/sonataflowgreetings.sw.json") - if err != nil { - panic("Can't read source file") - } - - if err != nil { - fmt.Println("Failed to create client") - fmt.Println(err.Error()) - } - platform := api.PlatformContainerBuild{ - ObjectReference: api.ObjectReference{ - Namespace: "sonataflow-builder", - Name: "testPlatform", - }, - Spec: api.PlatformContainerBuildSpec{ - BuildStrategy: api.ContainerBuildStrategyPod, - PublishStrategy: api.PlatformBuildPublishStrategyKaniko, - Registry: api.ContainerRegistrySpec{ - Insecure: true, - }, - Timeout: &metav1.Duration{ - Duration: 5 * time.Minute, - }, - }, - } - - cpuQty, _ := resource2.ParseQuantity("1") - memQty, _ := resource2.ParseQuantity("4Gi") - - build, err := builder.NewBuild(builder.ContainerBuilderInfo{FinalImageName: "greetings:latest", BuildUniqueName: "sonataflow-test", Platform: platform}). - WithClient(cli). - AddResource("Dockerfile", dockerFile).AddResource("greetings.sw.json", source). - Scheduler(). - WithAdditionalArgs([]string{"--build-arg=QUARKUS_PACKAGE_TYPE=mutable-jar", "--build-arg=QUARKUS_LAUNCH_DEVMODE=true", "--build-arg=SCRIPT_DEBUG=false"}). - WithResourceRequirements(v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceCPU: cpuQty, - v1.ResourceMemory: memQty, - }, - Requests: v1.ResourceList{ - v1.ResourceCPU: cpuQty, - v1.ResourceMemory: memQty, - }, - }). - Schedule() - if err != nil { - fmt.Println(err.Error()) - panic("Can't create build") - } - - // from now the Reconcile method can be called until the build is finished - for build.Status.Phase != api.ContainerBuildPhaseSucceeded && - build.Status.Phase != api.ContainerBuildPhaseError && - build.Status.Phase != api.ContainerBuildPhaseFailed { - fmt.Printf("\nBuild status is %s", build.Status.Phase) - build, err = builder.FromBuild(build).WithClient(cli).Reconcile() - if err != nil { - fmt.Println("Failed to run test") - panic(fmt.Errorf("build %v just failed", build)) - } - time.Sleep(10 * time.Second) - } - -} diff --git a/container-builder/util/log/log.go b/container-builder/util/log/log.go deleted file mode 100644 index 544fea7b..00000000 --- a/container-builder/util/log/log.go +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 log - -// Constants for different log level verbosity. -const ( - E = iota - W = iota - I = iota - D = iota -) diff --git a/container-builder/util/minikube/registry.go b/container-builder/util/minikube/registry.go deleted file mode 100644 index e564cbc8..00000000 --- a/container-builder/util/minikube/registry.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 minikube contains utilities for Minikube deployments -package minikube - -import ( - "context" - "strconv" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sclient "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -const ( - registryNamespace = "kube-system" -) - -// FindRegistry returns the Minikube addon registry location if any. -func FindRegistry(ctx context.Context, c client.Client) (*string, error) { - svcs := corev1.ServiceList{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Service", - }, - } - err := c.List(ctx, &svcs, - k8sclient.InNamespace(registryNamespace), - k8sclient.MatchingLabels{ - "kubernetes.io/minikube-addons": "registry", - }) - if err != nil { - return nil, err - } - if len(svcs.Items) == 0 { - return nil, nil - } - svc := svcs.Items[0] - ip := svc.Spec.ClusterIP - portStr := "" - if len(svc.Spec.Ports) > 0 { - port := svc.Spec.Ports[0].Port - if port > 0 && port != 80 { - portStr = ":" + strconv.FormatInt(int64(port), 10) - } - } - registry := ip + portStr - return ®istry, nil -} diff --git a/container-builder/util/registry/kep_1755.go b/container-builder/util/registry/kep_1755.go deleted file mode 100644 index 431d016b..00000000 --- a/container-builder/util/registry/kep_1755.go +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 registry - -import ( - "context" - - "k8s.io/apimachinery/pkg/util/yaml" - - corev1 "k8s.io/api/core/v1" - k8errors "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -// GetRegistryAddress KEP-1755 -// https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry -func GetRegistryAddress(ctx context.Context, c client.Client) (*string, error) { - config := corev1.ConfigMap{} - err := c.Get(ctx, ctrl.ObjectKey{Namespace: "kube-public", Name: "local-registry-hosting"}, &config) - if err != nil { - if k8errors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - if data, ok := config.Data["localRegistryHosting.v1"]; ok { - result := LocalRegistryHostingV1{} - if err := yaml.Unmarshal([]byte(data), &result); err != nil { - return nil, err - } - return &result.HostFromClusterNetwork, nil - } - return nil, nil -} - -// Copied from https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry -// LocalRegistryHostingV1 describes a local registry that developer tools can -// connect to. A local registry allows clients to load images into the local -// cluster by pushing to this registry. -type LocalRegistryHostingV1 struct { - // Host documents the host (hostname and port) of the registry, as seen from - // outside the cluster. - // - // This is the registry host that tools outside the cluster should push images - // to. - Host string `yaml:"host,omitempty"` - - // HostFromClusterNetwork documents the host (hostname and port) of the - // registry, as seen from networking inside the container pods. - // - // This is the registry host that tools running on pods inside the cluster - // should push images to. If not set, then tools inside the cluster should - // assume the local registry is not available to them. - HostFromClusterNetwork string `yaml:"hostFromClusterNetwork,omitempty"` - - // HostFromContainerRuntime documents the host (hostname and port) of the - // registry, as seen from the cluster's container runtime. - // - // When tools apply Kubernetes objects to the cluster, this host should be - // used for image name fields. If not set, users of this field should use the - // value of Host instead. - // - // Note that it doesn't make sense semantically to define this field, but not - // define Host or HostFromClusterNetwork. That would imply a way to pull - // images without a way to push images. - HostFromContainerRuntime string `yaml:"hostFromContainerRuntime,omitempty"` - - // Help contains a URL pointing to documentation for users on how to set - // up and configure a local registry. - // - // Tools can use this to nudge users to enable the registry. When possible, - // the writer should use as permanent a URL as possible to prevent drift - // (e.g., a version control SHA). - // - // When image pushes to a registry host specified in one of the other fields - // fail, the tool should display this help URL to the user. The help URL - // should contain instructions on how to diagnose broken or misconfigured - // registries. - Help string `yaml:"help,omitempty"` -} diff --git a/container-builder/util/test/client.go b/container-builder/util/test/client.go deleted file mode 100644 index d8526385..00000000 --- a/container-builder/util/test/client.go +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 test - -import ( - "context" - "fmt" - "strings" - - autoscalingv1 "k8s.io/api/autoscaling/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - "k8s.io/client-go/kubernetes" - fakeclientset "k8s.io/client-go/kubernetes/fake" - clientscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "k8s.io/client-go/scale" - fakescale "k8s.io/client-go/scale/fake" - "k8s.io/client-go/testing" - controller "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -// NewFakeClient ---. -func NewFakeClient(initObjs ...runtime.Object) client.Client { - scheme := clientscheme.Scheme - - c := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjs...).Build() - - clientset := fakeclientset.NewSimpleClientset(filterObjects(scheme, initObjs, func(gvk schema.GroupVersionKind) bool { - return !strings.Contains(gvk.Group, "knative") - })...) - replicasCount := make(map[string]int32) - fakescaleclient := fakescale.FakeScaleClient{} - fakescaleclient.AddReactor("update", "*", func(rawAction testing.Action) (bool, runtime.Object, error) { - action := rawAction.(testing.UpdateAction) // nolint: forcetypeassert - obj := action.GetObject().(*autoscalingv1.Scale) // nolint: forcetypeassert - replicas := obj.Spec.Replicas - key := fmt.Sprintf("%s:%s:%s/%s", action.GetResource().Group, action.GetResource().Resource, action.GetNamespace(), obj.GetName()) - replicasCount[key] = replicas - return true, &autoscalingv1.Scale{ - ObjectMeta: metav1.ObjectMeta{ - Name: obj.Name, - Namespace: action.GetNamespace(), - }, - Spec: autoscalingv1.ScaleSpec{ - Replicas: replicas, - }, - }, nil - }) - fakescaleclient.AddReactor("get", "*", func(rawAction testing.Action) (bool, runtime.Object, error) { - action := rawAction.(testing.GetAction) // nolint: forcetypeassert - key := fmt.Sprintf("%s:%s:%s/%s", action.GetResource().Group, action.GetResource().Resource, action.GetNamespace(), action.GetName()) - obj := &autoscalingv1.Scale{ - ObjectMeta: metav1.ObjectMeta{ - Name: action.GetName(), - Namespace: action.GetNamespace(), - }, - Spec: autoscalingv1.ScaleSpec{ - Replicas: replicasCount[key], - }, - } - return true, obj, nil - }) - - return &FakeClient{ - Client: c, - Interface: clientset, - scales: &fakescaleclient, - } -} - -func filterObjects(scheme *runtime.Scheme, input []runtime.Object, filter func(gvk schema.GroupVersionKind) bool) []runtime.Object { - var res []runtime.Object - for _, obj := range input { - kinds, _, _ := scheme.ObjectKinds(obj) - for _, k := range kinds { - if filter(k) { - res = append(res, obj) - break - } - } - } - return res -} - -// FakeClient ---. -type FakeClient struct { - controller.Client - kubernetes.Interface - scales *fakescale.FakeScaleClient -} - -// GetScheme ---. -func (c *FakeClient) GetScheme() *runtime.Scheme { - return clientscheme.Scheme -} - -func (c *FakeClient) GetConfig() *rest.Config { - return nil -} - -func (c *FakeClient) GetCurrentNamespace(kubeConfig string) (string, error) { - return "", nil -} - -// Patch mimicks patch for server-side apply and simply creates the obj. -func (c *FakeClient) Patch(ctx context.Context, obj controller.Object, patch controller.Patch, opts ...controller.PatchOption) error { - return c.Create(ctx, obj) -} - -func (c *FakeClient) Discovery() discovery.DiscoveryInterface { - return &FakeDiscovery{ - DiscoveryInterface: c.Interface.Discovery(), - } -} - -func (c *FakeClient) ScalesClient() (scale.ScalesGetter, error) { - return c.scales, nil -} - -type FakeDiscovery struct { - discovery.DiscoveryInterface -} - -func (f *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - // Normalize the fake discovery to behave like the real implementation when checking for openshift - if groupVersion == "image.openshift.io/v1" { - return nil, k8serrors.NewNotFound(schema.GroupResource{ - Group: "image.openshift.io", - }, "") - } - return f.DiscoveryInterface.ServerResourcesForGroupVersion(groupVersion) -} diff --git a/container-builder/util/util.go b/container-builder/util/util.go deleted file mode 100644 index 5da6d54b..00000000 --- a/container-builder/util/util.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 util - -import ( - "os" - "path/filepath" -) - -// ReadFile a safe wrapper of os.ReadFile. -func ReadFile(filename string) ([]byte, error) { - return os.ReadFile(filepath.Clean(filename)) -} - -func Pbool(value bool) *bool { - return &value -} - -func Pint(value int) *int { - return &value -} diff --git a/docs/CLI_E2E_TODO.md b/docs/CLI_E2E_TODO.md deleted file mode 100644 index c48f7a75..00000000 --- a/docs/CLI_E2E_TODO.md +++ /dev/null @@ -1,136 +0,0 @@ -# CLI E2E Tests - Integration TODO - -## Current Status - -The CLI has been successfully migrated to the logic-operator repository with all phases complete. However, the CLI e2e test suite currently expects the operator to be installed via OLM (Operator Lifecycle Manager), while our CI workflows deploy the operator directly from source. - -## The Issue - -**CLI e2e test setup (`cli/e2e-tests/main_test.go`):** -- Calls `InstallOperator()` which uses `operator install` command -- This command creates an OLM Subscription to install the operator from operatorhub.io -- Expects operator to be available as a published OLM package - -**Current CI workflow (`cli-e2e.yaml`):** -- Builds operator from source with `make docker-build` -- Loads image into KIND cluster -- Deploys operator directly with `make deploy` (not via OLM) - -## Solutions - -### Option 1: Create Local OLM Catalog (Recommended for CI) - -Build a local OLM catalog with our operator bundle: - -1. Build operator bundle image -2. Create catalog image with our bundle -3. Deploy catalog to cluster -4. Modify CLI's operator install to use local catalog -5. Run existing e2e tests unchanged - -**Pros:** -- Tests operator installation as users would experience it -- No changes to existing test code -- Tests the full OLM integration - -**Cons:** -- More complex CI setup -- Longer build times - -### Option 2: Adapt Tests for Direct Deployment - -Modify CLI e2e tests to work with directly deployed operator: - -1. Add environment variable to skip OLM-based installation -2. Assume operator is already deployed -3. Modify `InstallOperator()` to check for existing deployment instead -4. Update tests to work with pre-deployed operator - -**Pros:** -- Simpler CI setup -- Faster test execution -- Works with development workflows - -**Cons:** -- Doesn't test OLM installation path -- Requires test code changes - -### Option 3: Hybrid Approach - -Run two separate test suites: - -1. **Unit + Integration tests**: Deploy operator directly, run non-OLM tests -2. **Full E2E with OLM**: Separate workflow with OLM catalog setup - -**Pros:** -- Best of both worlds -- Fast feedback from unit/integration tests -- Full OLM coverage in dedicated workflow - -**Cons:** -- More complex workflow setup -- Higher maintenance burden - -## Recommendation - -Start with **Option 2** (adapt tests) for fast iteration, then add **Option 1** (OLM catalog) as a separate nightly/release workflow. - -## Test Categories - -Current CLI e2e tests: - -- `TestCreateProjectSuccess` - ✅ Works without operator -- `TestCreateProjectFail` - ✅ Works without operator -- `TestQuarkusCreateProjectSuccess` - ✅ Works without operator -- `TestQuarkusCreateProjectFail` - ✅ Works without operator -- `TestQuarkusConvertProjectSuccess` - ✅ Works without operator -- `TestQuarkusConvertProjectFailed` - ✅ Works without operator -- `TestQuarkusBuildCommand` - ⚠️ Requires Docker -- `TestRunCommand` - ⚠️ Requires Docker -- `TestQuarkusRunCommand` - ⚠️ Requires Docker -- `TestGenManifestProjectSuccess` - ✅ Works without operator -- `TestDeployProjectSuccess` - ❌ **Requires operator** -- `TestDeployProjectSuccessWithImageDefined` - ❌ **Requires operator** -- `TestDeployProjectSuccessWithoutResultEventRef` - ❌ **Requires operator** - -**Strategy:** -1. Short term: Run tests that don't need operator (create, gen-manifest, convert) -2. Medium term: Add Docker-in-Docker for build/run tests -3. Long term: Set up OLM catalog for deploy tests - -## Implementation Steps - -### Phase 1: Non-Operator Tests (Immediate) - -```yaml -- name: Run CLI e2e tests (non-operator) - working-directory: cli - run: | - go test -v ./e2e-tests/... -tags e2e_tests \ - -run "TestCreate|TestQuarkusCreate|TestQuarkusConvert|TestGenManifest" \ - -timeout 10m -``` - -### Phase 2: Build/Run Tests with Docker (Next) - -- Set up Docker-in-Docker in GitHub Actions -- Enable TestQuarkusBuildCommand, TestRunCommand, TestQuarkusRunCommand - -### Phase 3: Deploy Tests with Operator (Future) - -- Either adapt tests to use pre-deployed operator -- Or set up local OLM catalog with built operator - -## Files to Modify - -- `.github/workflows/cli-e2e.yaml` - Update test execution -- `cli/e2e-tests/main_test.go` - Add conditional operator installation -- `cli/e2e-tests/operator_helper.go` - Support pre-deployed operator mode - -## Success Criteria - -- [ ] All non-operator tests pass in CI -- [ ] Build/run tests pass with Docker setup -- [ ] Deploy tests pass with either approach -- [ ] Tests run in under 30 minutes -- [ ] Clear documentation of test categories and requirements diff --git a/docs/CLI_MIGRATION_METADATA.md b/docs/CLI_MIGRATION_METADATA.md deleted file mode 100644 index b90907fc..00000000 --- a/docs/CLI_MIGRATION_METADATA.md +++ /dev/null @@ -1,90 +0,0 @@ -# CLI Migration: Current Metadata Values - -**Source:** `apache/incubator-kie-tools/packages/kn-plugin-workflow` -**Date:** 2026-06-22 -**Purpose:** Document current values for migration to logic-operator - -## Build Metadata (Injected via ldflags) - -### Version Information -```go -// pkg/metadata/version.go -var PluginVersion string // Injected from package.json (currently "0.0.0") -``` - -### Image References -```go -// From env/index.js composition -var DevModeImage string // From @kie-tools/sonataflow-devmode-image/env -var BuilderImage string // From @kie-tools/sonataflow-builder-image/env -``` - -**Current image paths (from kie-tools):** -- DevMode: `quay.io/apache/incubator-kie-sonataflow-devmode:main` -- Builder: `quay.io/apache/incubator-kie-sonataflow-builder:main` - -### Quarkus Configuration -```go -// From env/index.js -var QuarkusPlatformGroupId string // Default: io.quarkus.platform -var QuarkusPlatformArtifactId string // Default: quarkus-bom -var QuarkusVersion string // From root-env -``` - -## Migration Strategy - -### New Metadata Structure -```go -// cli/pkg/metadata/metadata.go (NEW) -package metadata - -// Injected at build time via -ldflags -var ( - PluginVersion string // Git tag (e.g., "v2.0.0") - QuarkusVersion string // From root .env - BuilderImage string // From root .env - DevModeImage string // From root .env -) -``` - -### Build Command (NEW) -```makefile -# cli/Makefile -include ../.env - -VERSION ?= $(shell git describe --tags --always) - -LDFLAGS := -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.PluginVersion=$(VERSION) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.QuarkusVersion=$(QUARKUS_VERSION) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.BuilderImage=$(BUILDER_IMAGE) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.DevModeImage=$(DEVMODE_IMAGE) - -build: - go build -ldflags="$(LDFLAGS)" -o bin/kn-workflow cmd/main.go -``` - -### Root .env Values (inherit from parent) -```bash -# From /Users/ricferna/dev/github/kubesmarts/logic-operator/.env - -# Quarkus -QUARKUS_VERSION=3.8.1 - -# Images (updated to kubesmarts registry) -BUILDER_IMAGE=quay.io/kubesmarts/logic-operator-builder:main -DEVMODE_IMAGE=quay.io/kubesmarts/logic-operator-devmode:main - -# Or keep apache images initially: -# BUILDER_IMAGE=quay.io/apache/incubator-kie-sonataflow-builder:main -# DEVMODE_IMAGE=quay.io/apache/incubator-kie-sonataflow-devmode:main -``` - -## Files to Remove -- ❌ `env/index.js` - Replaced by Makefile + .env -- ❌ `package.json` - No longer using pnpm -- ❌ All Node.js build wrapper code - -## Files to Create/Update -- ✅ `cli/pkg/metadata/metadata.go` - Add QuarkusVersion, BuilderImage, DevModeImage vars -- ✅ `cli/Makefile` - Simplified build with ldflags injection -- ✅ `cli/README.md` - Update build instructions diff --git a/docs/CLI_MIGRATION_PLAN.md b/docs/CLI_MIGRATION_PLAN.md deleted file mode 100644 index 2336bc75..00000000 --- a/docs/CLI_MIGRATION_PLAN.md +++ /dev/null @@ -1,135 +0,0 @@ -# CLI Migration Plan: kn-plugin-workflow → logic-operator/cli - -**Status:** PLANNING - Execute AFTER CI is stable -**Estimated Effort:** 3-5 days -**Complexity:** MEDIUM - -## Overview - -Migrate `kn-plugin-workflow` from incubator-kie-tools monorepo to `logic-operator` repo as `cli/` subdirectory. - -**Current Location:** `/packages/kn-plugin-workflow` in incubator-kie-tools -**Target Location:** `/cli` in logic-operator -**Binary Name:** `kn-workflow` (unchanged) - -## Package Summary - -- **Size:** 75 Go files (~4,789 LOC) -- **Commands:** 9 top-level commands (create, run, deploy, undeploy, gen-manifest, quarkus, version, specs, operator) -- **Framework:** Cobra-based CLI -- **Build:** Go 1.25.0 + Makefile (currently wrapped by pnpm) -- **Tests:** 13 e2e test files - -## Key Dependencies - -### Internal (incubator-kie-tools) -- `sonataflow-operator/api` ✅ Already in logic-operator -- `sonataflow-operator/workflowproj` ✅ Already in logic-operator -- Image packages (builder, devmode) → Need new defaults - -### External (Go modules) -- k8s.io libraries (client-go, api, apimachinery) -- github.com/spf13/cobra -- github.com/docker/docker -- github.com/serverlessworkflow/sdk-go/v2 - -## Migration Phases - -### Phase 1: Preparation (1 day) -- [ ] Ensure CI is stable and green -- [ ] Create `cli/` directory structure -- [ ] Document current metadata values (Quarkus versions, image URLs) -- [ ] Decide on CLI versioning strategy (separate vs coupled with operator) - -### Phase 2: Code Migration (1 day) -- [ ] Copy entire kn-plugin-workflow structure to `cli/` -- [ ] Create `cli/go.mod` with new module path -- [ ] Update all import paths (~75 files): - ``` - OLD: github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow - NEW: github.com/kubesmarts/logic-operator/cli - - OLD: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/api - NEW: github.com/kubesmarts/logic-operator/api - - OLD: github.com/apache/incubator-kie-tools/packages/sonataflow-operator/workflowproj - NEW: github.com/kubesmarts/logic-operator/workflowproj - ``` -- [ ] Add `cli/` to `go.work` - -### Phase 3: Build System Refactoring (1 day) -- [ ] Remove pnpm/Node.js wrapper (delete `package.json`, `env/`) -- [ ] Simplify Makefile: - - Replace build-env system with environment variables - - Hardcode sensible defaults - - Support override via `.env` file -- [ ] Update metadata injection approach: - ```makefile - VERSION ?= $(shell git describe --tags --always) - QUARKUS_VERSION ?= 3.8.1 - BUILDER_IMAGE ?= quay.io/kubesmarts/incubator-kie-sonataflow-builder:main - DEVMODE_IMAGE ?= quay.io/kubesmarts/incubator-kie-sonataflow-devmode:main - - LDFLAGS = -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.PluginVersion=$(VERSION) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.QuarkusVersion=$(QUARKUS_VERSION) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.BuilderImage=$(BUILDER_IMAGE) \ - -X github.com/kubesmarts/logic-operator/cli/pkg/metadata.DevModeImage=$(DEVMODE_IMAGE) - ``` - -### Phase 4: Testing & Validation (1 day) -- [ ] Local build test: `cd cli && make build` -- [ ] Run unit tests: `go test ./...` -- [ ] Update e2e tests for new paths -- [ ] Verify operator integration -- [ ] Test all 9 commands smoke tests - -### Phase 5: CI/CD Integration (1 day) -- [ ] Add CLI build to `.github/workflows/` -- [ ] Multi-platform builds (darwin-amd64, darwin-arm64, linux-amd64, windows-amd64) -- [ ] Upload binaries as GitHub release artifacts -- [ ] Update README with new build instructions - -## Files to Keep -- ✅ All `.go` files (with updated imports) -- ✅ `Makefile` (simplified) -- ✅ `go.mod`, `go.sum` (updated) -- ✅ `e2e-tests/` and test files -- ✅ `LICENSE`, `README.md` -- ✅ `tools/` (Go tool dependencies) - -## Files to Drop -- ❌ `package.json` - No longer using pnpm -- ❌ `env/index.js` - Replaced with simpler env vars -- ❌ `node_modules/` - Not needed -- ❌ `dist/` - Will be regenerated -- ❌ `.vscode/`, `.idea/` - User-specific - -## Risks & Mitigations - -| Risk | Impact | Mitigation | -|------|--------|------------| -| Breaking import paths for downstream users | High | Document migration in changelog, provide transition period | -| Image URL changes | Medium | Use same quay.io/kubesmarts URLs, maintain compatibility | -| Lost git history | Low | Accept clean break OR use git subtree (adds complexity) | -| Build environment complexity | Medium | Test thoroughly, document new build process | - -## Success Criteria - -- [ ] `make build` produces working binary -- [ ] All unit tests pass -- [ ] E2E tests pass with local operator -- [ ] CI builds multi-platform binaries -- [ ] Documentation updated -- [ ] No dependencies on incubator-kie-tools repo - -## Post-Migration - -1. Update incubator-kie-tools to mark kn-plugin-workflow as deprecated -2. Add note pointing to logic-operator repo -3. Release first version from logic-operator (e.g., v2.0.0 to indicate new home) - -## Notes - -- **Version Strategy:** Recommend decoupling CLI version from operator version (semantic versioning independently) -- **Backwards Compatibility:** Consider keeping `kn-workflow` binary name but also providing `logic-cli` alias -- **Import Path:** `github.com/kubesmarts/logic-operator/cli` is clean and clear diff --git a/docs/migration/operator-sdk-migration-analysis.md b/docs/migration/operator-sdk-migration-analysis.md new file mode 100644 index 00000000..8cbaa116 --- /dev/null +++ b/docs/migration/operator-sdk-migration-analysis.md @@ -0,0 +1,234 @@ +# Operator SDK Migration Analysis - Logic Operator v2.0 + +## Current State + +**Operator SDK Version**: v1.35.0 (Current: June 2024) +**Latest Available**: v1.42.2 (Latest: June 2025) +**Kubebuilder Layout**: v4 +**Gap**: 7 minor versions behind + +## Current Structure + +``` +config/ ~2.1MB (CRDs, RBAC, manager, kustomize configs) +bundle/ ~1.9MB (OLM bundle manifests) +Makefile 562 lines +PROJECT 46 lines (references 4 deleted CRDs) +``` + +### What's in config/ + +- **config/crd/**: CRD definitions for deleted SonataFlow v1alpha08 resources +- **config/rbac/**: RBAC for deleted controllers +- **config/manager/**: Manager deployment referencing old image +- **config/samples/**: Sample CRs for deleted CRDs +- **config/default/**: Kustomization for deleted resources +- **config/prometheus/**: ServiceMonitor for old metrics +- **config/manifests/**: OLM metadata for old CRDs +- **config/scorecard/**: Scorecard config for old CRDs + +### What's in bundle/ + +- OLM bundle for SonataFlow v1alpha08 CRDs +- CSV (ClusterServiceVersion) with old metadata +- All deleted CRD schemas + +## Recommendation: **START FRESH** ✅ + +### Why Start Fresh? + +1. **100% of config/ is invalid** + - All CRDs reference deleted v1alpha08 API + - All RBAC rules reference deleted controllers + - All samples reference deleted resources + - Manager config references old images/args + +2. **Clean v2.0 design** + - New CRD group: `logic.kubesmarts.io` (vs old `sonataflow.org`) + - New CRD names: LogicPlatform, LogicFlowService, LogicFlowDefinition, LogicFlowRuntime + - No backward compatibility needed + - Fresh RBAC based on actual v2.0 needs + +3. **Upgrade to latest SDK v1.42.2** + - 7 minor versions of improvements + - Better kubebuilder v4 support + - Latest OLM bundle format + - Modern deployment patterns + +4. **Minimal effort to recreate** + - `operator-sdk init` takes 30 seconds + - `operator-sdk create api` generates scaffolding + - Can copy preserved code (discovery, utils) after scaffold + - Fresh Makefile with modern targets + +5. **Avoid technical debt** + - No leftover kustomize patches for deleted resources + - No outdated RBAC rules + - No confusing PROJECT file referencing old APIs + - Clean git history for v2.0 + +## Migration Plan + +### Phase 1: Scaffold Fresh Project (1-2 hours) + +```bash +# 1. Backup current state +mkdir -p /tmp/logic-operator-backup +cp -r . /tmp/logic-operator-backup/ + +# 2. Remove old scaffolding +rm -rf config/ bundle/ PROJECT Makefile + +# 3. Initialize fresh project with latest SDK +operator-sdk init \ + --domain kubesmarts.io \ + --repo github.com/kubesmarts/logic-operator \ + --project-name logic-operator + +# 4. Create v1 API group +operator-sdk create api \ + --group logic \ + --version v1 \ + --kind LogicPlatform \ + --resource \ + --controller + +operator-sdk create api \ + --group logic \ + --version v1 \ + --kind LogicFlowService \ + --resource \ + --controller + +operator-sdk create api \ + --group logic \ + --version v1 \ + --kind LogicFlowDefinition \ + --resource \ + --controller + +operator-sdk create api \ + --group logic \ + --version v1 \ + --kind LogicFlowRuntime \ + --resource \ + --controller +``` + +### Phase 2: Restore Preserved Code (1 hour) + +```bash +# Copy preserved utilities +cp -r /tmp/logic-operator-backup/internal/controller/discovery internal/controller/ +cp -r /tmp/logic-operator-backup/internal/controller/cfg internal/controller/ +cp -r /tmp/logic-operator-backup/internal/controller/knative internal/controller/ +cp -r /tmp/logic-operator-backup/internal/controller/openshift internal/controller/ +cp -r /tmp/logic-operator-backup/utils utils/ + +# Copy other preserved files +cp /tmp/logic-operator-backup/log/*.go log/ +cp /tmp/logic-operator-backup/CLAUDE.md . +cp /tmp/logic-operator-backup/cli/DEPRECATED.md cli/ +``` + +### Phase 3: Implement CRD Types (2-3 hours) + +Based on ADR-001, implement: +- `api/v1/logicplatform_types.go` +- `api/v1/logicflowservice_types.go` +- `api/v1/logicflowdefinition_types.go` +- `api/v1/logicflowruntime_types.go` + +### Phase 4: Generate Manifests (30 min) + +```bash +make generate +make manifests +make bundle +``` + +Fresh, clean config/ and bundle/ generated from v2.0 CRDs. + +### Phase 5: Update Workflows (30 min) + +Update `.github/workflows/` to use SDK v1.42.2: +```yaml +OPERATOR_SDK_VERSION=v1.42.2 +``` + +## What We Lose (Nothing Important) + +- ❌ Old SonataFlow CRD configs (already deleted from API) +- ❌ Old RBAC rules (will regenerate for v2.0) +- ❌ Old samples (will create new v2.0 samples) +- ❌ Old bundle (will generate fresh for v2.0) + +## What We Keep + +- ✅ All Go code (cmd/, internal/, utils/, api/condition_types.go, api/status_types.go) +- ✅ Discovery subsystem +- ✅ Generic utilities +- ✅ git history +- ✅ README, docs, workflows (updated) +- ✅ .env configuration + +## Alternative: Incremental Cleanup (NOT RECOMMENDED) + +If you want to keep existing structure: +1. Manually delete all v1alpha08 references in config/ +2. Manually update PROJECT file +3. Manually update Makefile targets +4. Manually update RBAC rules +5. Manually update bundle/ + +**Estimated effort**: 4-6 hours +**Result**: Still have outdated SDK v1.35.0, leftover cruft + +vs. + +**Fresh start effort**: 3-5 hours +**Result**: Latest SDK v1.42.2, clean structure, no technical debt + +## Recommendation + +**DELETE** the following and start fresh: +``` +config/ +bundle/ +PROJECT +Makefile +``` + +**KEEP** everything else: +``` +api/ (status_types.go, condition_types.go, version/) +cmd/ +internal/controller/ (discovery/, cfg/, knative/, openshift/) +utils/ +log/ +.github/ +README.md +CLAUDE.md +cli/DEPRECATED.md +.env* +go.mod, go.work +``` + +## Next Steps + +1. Get user approval for fresh scaffold +2. Run operator-sdk init with new domain/group +3. Create v1 APIs for 4 CRDs +4. Implement CRD types based on ADR-001 +5. Generate fresh manifests +6. Test build and deployment + +## Benefits Summary + +✅ Latest Operator SDK (v1.42.2) +✅ Clean v2.0 CRD structure +✅ Modern kubebuilder v4 scaffolding +✅ No technical debt from v1alpha08 +✅ Fresh RBAC matching actual needs +✅ Clean OLM bundle for v2.0 +✅ Easier to maintain going forward diff --git a/env/index.js b/env/index.js deleted file mode 100644 index 7145c9d7..00000000 --- a/env/index.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { varsWithName, composeEnv, getOrDefault } = require("@kie-tools-scripts/build-env"); - -const sonataflowBuilderImageEnv = require("@kie-tools/sonataflow-builder-image/env"); -const sonataflowDevModeImageEnv = require("@kie-tools/sonataflow-devmode-image/env"); -const kogitoJobsServiceEphemeralImageEnv = require("@kie/kogito-jobs-service-ephemeral-image/env"); -const kogitoJobsServicePostgresqlImageEnv = require("@kie/kogito-jobs-service-postgresql-image/env"); -const kogitoDataIndexEphemeralImageEnv = require("@kie/kogito-data-index-ephemeral-image/env"); -const kogitoDataIndexPostgresqlImageEnv = require("@kie/kogito-data-index-postgresql-image/env"); -const kogitoDBMigratorToolImageEnv = require("@kie-tools/kogito-db-migrator-tool-image/env"); -const rootEnv = require("@kie-tools/root-env/env"); - -module.exports = composeEnv([rootEnv, sonataflowBuilderImageEnv, sonataflowDevModeImageEnv], { - vars: varsWithName({ - SONATAFLOW_OPERATOR__registry: { - default: "docker.io", - description: "E.g., `docker.io` or `quay.io`.", - }, - SONATAFLOW_OPERATOR__account: { - default: "apache", - description: "E.g,. `apache` or `kie-tools-bot`", - }, - SONATAFLOW_OPERATOR__name: { - default: "incubator-kie-sonataflow-operator", - description: "Name of the image itself.", - }, - SONATAFLOW_OPERATOR__buildTag: { - default: rootEnv.env.root.streamName, - description: "Tag version of this image. E.g., `main` or `10.0.x` or `10.0.0", - }, - SONATAFLOW_OPERATOR__platformTag: { - default: rootEnv.env.root.streamName, - description: - "Tag version the platform Tag - The default tag used for all the images managed by the operator. It changes the version.go file. E.g., `main` or `10.0.x` or `10.0.0", - }, - SONATAFLOW_OPERATOR__sonataflowBuilderImage: { - default: `${sonataflowBuilderImageEnv.env.sonataflowBuilderImage.registry}/${sonataflowBuilderImageEnv.env.sonataflowBuilderImage.account}/${sonataflowBuilderImageEnv.env.sonataflowBuilderImage.name}:${sonataflowBuilderImageEnv.env.sonataflowBuilderImage.buildTag}`, - description: "Sonataflow Builder image", - }, - SONATAFLOW_OPERATOR__sonataflowDevModeImage: { - default: `${sonataflowDevModeImageEnv.env.sonataflowDevModeImage.registry}/${sonataflowDevModeImageEnv.env.sonataflowDevModeImage.account}/${sonataflowDevModeImageEnv.env.sonataflowDevModeImage.name}:${sonataflowDevModeImageEnv.env.sonataflowDevModeImage.buildTag}`, - description: "Sonataflow DevMode image", - }, - SONATAFLOW_OPERATOR__kogitoJobsServiceEphemeralImage: { - default: `${kogitoJobsServiceEphemeralImageEnv.env.kogitoJobsServiceEphemeralImage.registry}/${kogitoJobsServiceEphemeralImageEnv.env.kogitoJobsServiceEphemeralImage.account}/${kogitoJobsServiceEphemeralImageEnv.env.kogitoJobsServiceEphemeralImage.name}:${kogitoJobsServiceEphemeralImageEnv.env.kogitoJobsServiceEphemeralImage.buildTag}`, - description: "Kogito Jobs Service Ephemeral image", - }, - SONATAFLOW_OPERATOR__kogitoJobsServicePostgresqlImage: { - default: `${kogitoJobsServicePostgresqlImageEnv.env.kogitoJobsServicePostgresqlImage.registry}/${kogitoJobsServicePostgresqlImageEnv.env.kogitoJobsServicePostgresqlImage.account}/${kogitoJobsServicePostgresqlImageEnv.env.kogitoJobsServicePostgresqlImage.name}:${kogitoJobsServicePostgresqlImageEnv.env.kogitoJobsServicePostgresqlImage.buildTag}`, - description: "Kogito Jobs Service PostgreSQL image", - }, - SONATAFLOW_OPERATOR__kogitoDataIndexEphemeralImage: { - default: `${kogitoDataIndexEphemeralImageEnv.env.kogitoDataIndexEphemeralImage.registry}/${kogitoDataIndexEphemeralImageEnv.env.kogitoDataIndexEphemeralImage.account}/${kogitoDataIndexEphemeralImageEnv.env.kogitoDataIndexEphemeralImage.name}:${kogitoDataIndexEphemeralImageEnv.env.kogitoDataIndexEphemeralImage.buildTag}`, - description: "Kogito Data Index Ephemeral image", - }, - SONATAFLOW_OPERATOR__kogitoDataIndexPostgresqlImage: { - default: `${kogitoDataIndexPostgresqlImageEnv.env.kogitoDataIndexPostgresqlImage.registry}/${kogitoDataIndexPostgresqlImageEnv.env.kogitoDataIndexPostgresqlImage.account}/${kogitoDataIndexPostgresqlImageEnv.env.kogitoDataIndexPostgresqlImage.name}:${kogitoDataIndexPostgresqlImageEnv.env.kogitoDataIndexPostgresqlImage.buildTag}`, - description: "Kogito Data Index PostgreSQL image", - }, - SONATAFLOW_OPERATOR__kogitoDBMigratorToolImage: { - default: `${kogitoDBMigratorToolImageEnv.env.kogitoDbMigratorToolImage.registry}/${kogitoDBMigratorToolImageEnv.env.kogitoDbMigratorToolImage.account}/${kogitoDBMigratorToolImageEnv.env.kogitoDbMigratorToolImage.name}:${kogitoDBMigratorToolImageEnv.env.kogitoDbMigratorToolImage.buildTag}`, - description: "Kogito DB Migrator image", - }, - SONATAFLOW_OPERATOR_pinImageSHABundleTool: { - default: "", - description: - "Which tool to pin related images when generating the operator bundle. If empty, no SHA is generated from the images. Possible values are docker|podman|skopeo.", - }, - }), - get env() { - return { - sonataFlowOperator: { - registry: getOrDefault(this.vars.SONATAFLOW_OPERATOR__registry), - account: getOrDefault(this.vars.SONATAFLOW_OPERATOR__account), - name: getOrDefault(this.vars.SONATAFLOW_OPERATOR__name), - buildTag: getOrDefault(this.vars.SONATAFLOW_OPERATOR__buildTag), - platformTag: getOrDefault(this.vars.SONATAFLOW_OPERATOR__platformTag), - version: require("../package.json").version, - sonataflowBuilderImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__sonataflowBuilderImage), - sonataflowDevModeImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__sonataflowDevModeImage), - kogitoJobsServiceEphemeralImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__kogitoJobsServiceEphemeralImage), - kogitoJobsServicePostgresqlImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__kogitoJobsServicePostgresqlImage), - kogitoDataIndexEphemeralImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__kogitoDataIndexEphemeralImage), - kogitoDataIndexPostgresqlImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__kogitoDataIndexPostgresqlImage), - kogitoDBMigratorToolImage: getOrDefault(this.vars.SONATAFLOW_OPERATOR__kogitoDBMigratorToolImage), - pinImageSHABundleTool: getOrDefault(this.vars.SONATAFLOW_OPERATOR_pinImageSHABundleTool), - }, - }; - }, -}); diff --git a/go.mod b/go.mod index aba20701..ec94a81f 100644 --- a/go.mod +++ b/go.mod @@ -2,134 +2,113 @@ module github.com/kubesmarts/logic-operator go 1.26.0 -// Internal dependencies -replace ( - github.com/kubesmarts/logic-operator/api => ./api - github.com/kubesmarts/logic-operator/container-builder => ./container-builder - github.com/kubesmarts/logic-operator/workflowproj => ./workflowproj -) - -// Direct dependencies (please keep organized, no indirects) require ( - github.com/cloudevents/sdk-go/v2 v2.15.2 - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/go-logr/logr v1.4.2 // indirect - github.com/imdario/mergo v0.3.16 - github.com/kubesmarts/logic-operator/api v0.0.0 - github.com/kubesmarts/logic-operator/container-builder v0.0.0 - github.com/kubesmarts/logic-operator/workflowproj v0.0.0 - github.com/magiconair/properties v1.8.7 - github.com/onsi/ginkgo/v2 v2.19.0 - github.com/onsi/gomega v1.33.1 - github.com/openshift/api v0.0.0-20240618205917-987b8890c273 - github.com/openshift/client-go v0.0.0-20240528061634-b054aa794d87 - github.com/pkg/errors v0.9.1 - github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.55.1 - github.com/serverlessworkflow/sdk-go/v2 v2.5.0 - github.com/stretchr/testify v1.9.0 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/client-go v0.31.1 - k8s.io/klog/v2 v2.130.1 - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 - knative.dev/eventing v0.39.4 - knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c - knative.dev/serving v0.39.4 - sigs.k8s.io/controller-runtime v0.19.0 - sigs.k8s.io/yaml v1.4.0 + github.com/cloudevents/sdk-go/v2 v2.16.2 + github.com/magiconair/properties v1.8.10 + github.com/onsi/ginkgo/v2 v2.27.2 + github.com/onsi/gomega v1.38.2 + github.com/openshift/api v0.0.0-20260623101811-c5eb460d04e3 + github.com/stretchr/testify v1.11.1 + k8s.io/api v0.35.6 + k8s.io/apimachinery v0.35.6 + k8s.io/client-go v0.35.6 + k8s.io/klog/v2 v2.140.0 + knative.dev/pkg v0.0.0-20260622140654-39ebae2ee2dc + sigs.k8s.io/controller-runtime v0.21.0 ) require ( - contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d // indirect - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect + cel.dev/expr v0.25.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/blendle/zapdriver v1.3.1 // indirect - github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudevents/sdk-go/sql/v2 v2.13.0 // indirect - github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.25.4 // indirect + github.com/go-openapi/swag/cmdutils v0.25.4 // indirect + github.com/go-openapi/swag/conv v0.25.4 // indirect + github.com/go-openapi/swag/fileutils v0.25.4 // indirect + github.com/go-openapi/swag/jsonname v0.25.4 // indirect + github.com/go-openapi/swag/jsonutils v0.25.4 // indirect + github.com/go-openapi/swag/loading v0.25.4 // indirect + github.com/go-openapi/swag/mangling v0.25.4 // indirect + github.com/go-openapi/swag/netutils v0.25.4 // indirect + github.com/go-openapi/swag/stringutils v0.25.4 // indirect + github.com/go-openapi/swag/typeutils v0.25.4 // indirect + github.com/go-openapi/swag/yamlutils v0.25.4 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-containerregistry v0.13.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/cel-go v0.26.0 // indirect + github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/jpillora/backoff v1.0.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moby/spdystream v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pb33f/libopenapi v0.8.4 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/relvacode/iso8601 v1.4.0 // indirect - github.com/rickb777/date v1.13.0 // indirect - github.com/rickb777/plural v1.2.1 // indirect - github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/santhosh-tekuri/jsonschema/v5 v5.3.0 // indirect - github.com/sosodev/duration v1.3.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/spf13/cobra v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect - go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/sdk v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.38.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/api v0.169.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.67.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + go.uber.org/zap v1.28.0 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.38.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.46.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/grpc v1.81.1 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - knative.dev/networking v0.0.0-20231017124814-2a7676e912b7 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/apiextensions-apiserver v0.35.6 // indirect + k8s.io/apiserver v0.35.6 // indirect + k8s.io/component-base v0.35.6 // indirect + k8s.io/kube-openapi v0.0.0-20260519202549-bbf5c5577288 // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index b1cd9dea..f4c7b55b 100644 --- a/go.sum +++ b/go.sum @@ -1,796 +1,286 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d h1:LblfooH1lKOpp1hIhukktmSAxFkqMPFk9KR6iZ0MJNI= -contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= -github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudevents/sdk-go/sql/v2 v2.13.0 h1:gMJvQ3XFkygY9JmrusgK80d9yRAb8+J3X8IA1OC+oc0= -github.com/cloudevents/sdk-go/sql/v2 v2.13.0/go.mod h1:XZRQBCgRreddIpQrdjBJQUrRg3BCs3aikplJQkHrK44= -github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc= -github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cloudevents/sdk-go/v2 v2.16.2 h1:ZYDFrYke4FD+jM8TZTJJO6JhKHzOQl2oqpFK1D+NnQM= +github.com/cloudevents/sdk-go/v2 v2.16.2/go.mod h1:laOcGImm4nVJEU+PHnUrKL56CKmRL65RlQF0kRmW/kg= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= +github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= +github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= +github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= +github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= +github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= +github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= +github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= +github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= +github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= +github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= +github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= +github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= +github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= +github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= +github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= +github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= +github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= +github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= +github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= +github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= +github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k= -github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= -github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= +github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/openshift/api v0.0.0-20240618205917-987b8890c273 h1:a2B5ocKga0ckZlb4fxneG90xzfC0rLCcxzVbte8USEI= -github.com/openshift/api v0.0.0-20240618205917-987b8890c273/go.mod h1:OOh6Qopf21pSzqNVCB5gomomBXb8o5sGKZxG2KNpaXM= -github.com/openshift/client-go v0.0.0-20240528061634-b054aa794d87 h1:JtLhaGpSEconE+1IKmIgCOof/Len5ceG6H1pk43yv5U= -github.com/openshift/client-go v0.0.0-20240528061634-b054aa794d87/go.mod h1:3IPD4U0qyovZS4EFady2kqY32m8lGcbs/Wx+yprg9z8= -github.com/pb33f/libopenapi v0.8.4 h1:hP6etldkapogvEfILaCVrBNh9DwzK/ZKGrNPm3qAIwU= -github.com/pb33f/libopenapi v0.8.4/go.mod h1:lvUmCtjgHUGVj6WzN3I5/CS9wkXtyN3Ykjh6ZZP5lrI= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/openshift/api v0.0.0-20260623101811-c5eb460d04e3 h1:/IBS3zzQk3CfvBLF18oaoNVeqZCEjOrFNJSGjSybPsU= +github.com/openshift/api v0.0.0-20260623101811-c5eb460d04e3/go.mod h1:Jm45pE7O6/G0tYYhiLzNyZykTjmf9BfhsKYuGfLLwTE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.55.1 h1:IIEF5Sp5jDnqRNoHH5fPLNOsScMhmfyWmFP7m04jokc= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.55.1/go.mod h1:/xf16Bu3krDP6G5WhrJL9avDnLW/AN0g7hAIK63mbes= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXUJs= -github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= -github.com/rickb777/date v1.13.0 h1:+8AmwLuY1d/rldzdqvqTEg7107bZ8clW37x4nsdG3Hs= -github.com/rickb777/date v1.13.0/go.mod h1:GZf3LoGnxPWjX+/1TXOuzHefZFDovTyNLHDMd3qH70k= -github.com/rickb777/plural v1.2.1 h1:UitRAgR70+yHFt26Tmj/F9dU9aV6UfjGXSbO1DcC9/U= -github.com/rickb777/plural v1.2.1/go.mod h1:j058+3M5QQFgcZZ2oKIOekcygoZUL8gKW5yRO14BuAw= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.0 h1:uIkTLo0AGRc8l7h5l9r+GcYi9qfVPt6lD4/bhmzfiKo= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0 h1:bvD461rbaj0PcRjRwsBt7tqHie2M10otryB+BjzHg5Q= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0/go.mod h1:kuvTQCTAb9vzDaeJ1JPY+sBGiHr9OX1g/Rxuk82c8mI= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= -github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.10.0 h1:a5/WeUlSDCvV5a45ljW2ZFtV0bTDpkfSAj3uqB6Sc+0= +github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE= +github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= -github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 h1:4YsVu3B8+3qtWYYrsUYgn0OG78pN0rnNPRGX4SbokQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0/go.mod h1:+wnlSn0mD1ADVMe3v9Z/WIaiz6q6gL2J/ejaAmdmv80= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0 h1:qazEJlUOQzhCpzQpFETGby7EdqjI1wsd0W+6Gg1SCTU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0/go.mod h1:fOD2Yefuxixkx3ahVNf0O/PERb6r4OlbxfATVnYvzCo= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512001501-aaeff5de670a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= +golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= +gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= +gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/eventing v0.39.4 h1:MFgS+cLIkB6HFdvuoI3XznNEGT84294LHWjCg7RK8cM= -knative.dev/eventing v0.39.4/go.mod h1:MlEiEcHALqZnu0OFMuWdJfjBzM7HlSJfk8pQbTcIy4o= -knative.dev/networking v0.0.0-20231017124814-2a7676e912b7 h1:6+1icZuxiZO1paFZ4d/ysKWVG2M4WB7OxNJNyLG0P/E= -knative.dev/networking v0.0.0-20231017124814-2a7676e912b7/go.mod h1:1gcHoIVG47ekQWjkddqRq+/7tWRh+CB9W4k/NAcdRbk= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c/go.mod h1:HHRXEd7ZlFpthgE+rwAZ6MUVnuJOAeolnaFSthXloUQ= -knative.dev/serving v0.39.4 h1:9IlFE7GsORKhI92DIZbF88hplQYM73T1l4W50UxZwF8= -knative.dev/serving v0.39.4/go.mod h1:bWylSgwnRZeL659qy7m3/TZioYk25TIfusPUEeR695A= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +k8s.io/api v0.35.6 h1:phPzP79F3kcONsD2TzmDiITNCV6/1Z5U3CCEcjtsXzI= +k8s.io/api v0.35.6/go.mod h1:GWKUaIp24fuDFigAgnhr9EJOKDqspnwPjYlpDca5B4U= +k8s.io/apiextensions-apiserver v0.35.6 h1:fyzp3i+PAbB/jSNau9LF0rMuUTUUyybR02BpYhT1YKI= +k8s.io/apiextensions-apiserver v0.35.6/go.mod h1:kkCbFS495cT53wOqNwWnQei759bkvgn6OqE0R8b3DEA= +k8s.io/apimachinery v0.35.6 h1:ASSpfmmsOArKb2Hsu8gGlIcbIcEMVTboI3FfsfYuQ8k= +k8s.io/apimachinery v0.35.6/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= +k8s.io/apiserver v0.35.6 h1:VWYg2S0wlAmN3URFpVeuLa4PP2RCpTFg1nvlUHOy2C8= +k8s.io/apiserver v0.35.6/go.mod h1:wajGSrXO9w+lx69jYq4SaE4Xxw5KxxwvVD1zbttYA2E= +k8s.io/client-go v0.35.6 h1:qZQv9a5B4YlIpXhFBwsI9qPOOJC6Z8lk9lkEWmrmus8= +k8s.io/client-go v0.35.6/go.mod h1:LOO6N1EhxdQAzYIZ/73cJVyb3gixrMY6ZDJcJ/ANfsY= +k8s.io/component-base v0.35.6 h1:dTkck9uefkIrKn7wRCEYiDWNUvHd8UdwZCcVafmHgL4= +k8s.io/component-base v0.35.6/go.mod h1:qcNKrspACsqR+vgUJXkWzwtgUGkURcnrus41o92jjpk= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kube-openapi v0.0.0-20260519202549-bbf5c5577288 h1:A7Lby6ekC6nv+6oO38huCMFBRP0Os+tIeq1GkwxOQes= +k8s.io/kube-openapi v0.0.0-20260519202549-bbf5c5577288/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +knative.dev/pkg v0.0.0-20260622140654-39ebae2ee2dc h1:i2GrJuRdTFd4sNWocwefVGwuSOkOPjtadEWRTiGsEOY= +knative.dev/pkg v0.0.0-20260622140654-39ebae2ee2dc/go.mod h1:Ve19ZYW7DwIfQL4oCT9t9zmPp4egv0KacKVPXUcivDQ= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= +sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/go.work b/go.work deleted file mode 100644 index fcbeee40..00000000 --- a/go.work +++ /dev/null @@ -1,30 +0,0 @@ -go 1.26.0 - -use ( - . - ./api - ./cli - ./container-builder - ./workflowproj -) - -replace ( - github.com/RHsyseng/operator-utils => github.com/RHsyseng/operator-utils v1.4.13 - github.com/openshift/api => github.com/openshift/api v0.0.0-20230522130544-0eef84f63102 - github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb - - // Main dependencies sync - github.com/serverlessworkflow/sdk-go/v2 => github.com/serverlessworkflow/sdk-go/v2 v2.5.0 - k8s.io/api => k8s.io/api v0.31.1 - k8s.io/apimachinery => k8s.io/apimachinery v0.31.1 - k8s.io/client-go => k8s.io/client-go v0.31.1 - k8s.io/klog/v2 => k8s.io/klog/v2 v2.130.1 - - // Knative 1.12 - knative.dev/eventing => knative.dev/eventing v0.39.4 - knative.dev/pkg => knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c - knative.dev/serving => knative.dev/serving v0.39.4 - - sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.19.0 - sigs.k8s.io/yaml => sigs.k8s.io/yaml v1.4.0 -) diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index 72b39049..00000000 --- a/go.work.sum +++ /dev/null @@ -1,4173 +0,0 @@ -4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 h1:SC+c6A1qTFstO9qmB86mPV2IpYme/2ZoEQ0hrP+wo+Q= -bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= -bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U= -cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= -cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= -cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y= -cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= -cel.dev/expr v0.16.2 h1:RwRhoH17VhAu9U5CMvMhH1PDVgf0tuz9FT+24AfMLfU= -cel.dev/expr v0.16.2/go.mod h1:gXngZQMkWJoSbE8mOzehJlXQyubn/Vg0vR9/F3W7iw8= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.98.0 h1:w6LozQJyDDEyhf64Uusu1LCcnLt0I1VMLiJC2kV+eXk= -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0 h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accessapproval v1.7.1 h1:/5YjNhR6lzCvmJZAnByYkfEgWjfAKwYP6nkuTk6nKFE= -cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= -cloud.google.com/go/accessapproval v1.7.4 h1:ZvLvJ952zK8pFHINjpMBY5k7LTAp/6pBf50RDMRgBUI= -cloud.google.com/go/accessapproval v1.7.5 h1:uzmAMSgYcnlHa9X9YSQZ4Q1wlfl4NNkZyQgho1Z6p04= -cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0= -cloud.google.com/go/accessapproval v1.8.2 h1:h4u1MypgeYXTGvnNc1luCBLDN4Kb9Re/gw0Atvoi8HE= -cloud.google.com/go/accessapproval v1.8.2/go.mod h1:aEJvHZtpjqstffVwF/2mCXXSQmpskyzvw6zKLvLutZM= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0 h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/accesscontextmanager v1.8.1 h1:WIAt9lW9AXtqw/bnvrEUaE8VG/7bAAeMzRCBGMkc4+w= -cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= -cloud.google.com/go/accesscontextmanager v1.8.4 h1:Yo4g2XrBETBCqyWIibN3NHNPQKUfQqti0lI+70rubeE= -cloud.google.com/go/accesscontextmanager v1.8.5 h1:2GLNaNu9KRJhJBFTIVRoPwk6xE5mUDgD47abBq4Zp/I= -cloud.google.com/go/accesscontextmanager v1.8.5/go.mod h1:TInEhcZ7V9jptGNqN3EzZ5XMhT6ijWxTGjzyETwmL0Q= -cloud.google.com/go/accesscontextmanager v1.9.2 h1:P0uVixQft8aacbZ7VDZStNZdrftF24Hk8JkA3kfvfqI= -cloud.google.com/go/accesscontextmanager v1.9.2/go.mod h1:T0Sw/PQPyzctnkw1pdmGAKb7XBA84BqQzH0fSU7wzJU= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0 h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/aiplatform v1.50.0 h1:J89aj+lqwtjn0qpQBMVaiOmDxBkKDEKUwl+GL19RRpc= -cloud.google.com/go/aiplatform v1.50.0/go.mod h1:IRc2b8XAMTa9ZmfJV1BCCQbieWWvDnP1A8znyz5N7y4= -cloud.google.com/go/aiplatform v1.52.0 h1:TbbUvAujxXlSlbG5+XBtJEEEUyGjtyJxZ/VIlvz9Dps= -cloud.google.com/go/aiplatform v1.52.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv65IHILGA//VEU= -cloud.google.com/go/aiplatform v1.54.0 h1:wH7OYl9Vq/5tupok0BPTFY9xaTLb0GxkReHtB5PF7cI= -cloud.google.com/go/aiplatform v1.58.2/go.mod h1:c3kCiVmb6UC1dHAjZjcpDj6ZS0bHQ2slL88ZjC2LtlA= -cloud.google.com/go/aiplatform v1.60.0 h1:0cSrii1ZeLr16MbBoocyy5KVnrSdiQ3KN/vtrTe7RqE= -cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM= -cloud.google.com/go/aiplatform v1.69.0 h1:XvBzK8e6/6ufbi/i129Vmn/gVqFwbNPmRQ89K+MGlgc= -cloud.google.com/go/aiplatform v1.69.0/go.mod h1:nUsIqzS3khlnWvpjfJbP+2+h+VrFyYsTm7RNCAViiY8= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0 h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/analytics v0.21.3 h1:TFBC1ZAqX9/jL56GEXdLrVe5vT3I22bDVWyDwZX4IEg= -cloud.google.com/go/analytics v0.21.3/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/analytics v0.21.6 h1:fnV7B8lqyEYxCU0LKk+vUL7mTlqRAq4uFlIthIdr/iA= -cloud.google.com/go/analytics v0.23.0 h1:Q+y94XH84jM8SK8O7qiY/PJRexb6n7dRbQ6PiUa4YGM= -cloud.google.com/go/analytics v0.23.0/go.mod h1:YPd7Bvik3WS95KBok2gPXDqQPHy08TsCQG6CdUCb+u0= -cloud.google.com/go/analytics v0.25.2 h1:KgJ5Taxtsnro/co7WIhmAHi5pzYAtvxu8LMqenPAlSo= -cloud.google.com/go/analytics v0.25.2/go.mod h1:th0DIunqrhI1ZWVlT3PH2Uw/9ANX8YHfFDEPqf/+7xM= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0 h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigateway v1.6.1 h1:aBSwCQPcp9rZ0zVEUeJbR623palnqtvxJlUyvzsKGQc= -cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= -cloud.google.com/go/apigateway v1.6.4 h1:VVIxCtVerchHienSlaGzV6XJGtEM9828Erzyr3miUGs= -cloud.google.com/go/apigateway v1.6.5 h1:sPXnpk+6TneKIrjCjcpX5YGsAKy3PTdpIchoj8/74OE= -cloud.google.com/go/apigateway v1.6.5/go.mod h1:6wCwvYRckRQogyDDltpANi3zsCDl6kWi0b4Je+w2UiI= -cloud.google.com/go/apigateway v1.7.2 h1:TRB5q0vvbT5Yx4bNSCWlqLJFJnhc7tDlCR9ccpo1vzg= -cloud.google.com/go/apigateway v1.7.2/go.mod h1:+weId+9aR9J6GRwDka7jIUSrKEX60XGcikX7dGU8O7M= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0 h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeconnect v1.6.1 h1:6u/jj0P2c3Mcm+H9qLsXI7gYcTiG9ueyQL3n6vCmFJM= -cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= -cloud.google.com/go/apigeeconnect v1.6.4 h1:jSoGITWKgAj/ssVogNE9SdsTqcXnryPzsulENSRlusI= -cloud.google.com/go/apigeeconnect v1.6.5 h1:CrfIKv9Go3fh/QfQgisU3MeP90Ww7l/sVGmr3TpECo8= -cloud.google.com/go/apigeeconnect v1.6.5/go.mod h1:MEKm3AiT7s11PqTfKE3KZluZA9O91FNysvd3E6SJ6Ow= -cloud.google.com/go/apigeeconnect v1.7.2 h1:GHg0ddEQUZ08C1qC780P5wwY/jaIW8UtxuRQXLLuRXs= -cloud.google.com/go/apigeeconnect v1.7.2/go.mod h1:he/SWi3A63fbyxrxD6jb67ak17QTbWjva1TFbT5w8Kw= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0 h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apigeeregistry v0.7.1 h1:hgq0ANLDx7t2FDZDJQrCMtCtddR/pjCqVuvQWGrQbXw= -cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= -cloud.google.com/go/apigeeregistry v0.8.2 h1:DSaD1iiqvELag+lV4VnnqUUFd8GXELu01tKVdWZrviE= -cloud.google.com/go/apigeeregistry v0.8.3 h1:C+QU2K+DzDjk4g074ouwHQGkoff1h5OMQp6sblCVreQ= -cloud.google.com/go/apigeeregistry v0.8.3/go.mod h1:aInOWnqF4yMQx8kTjDqHNXjZGh/mxeNlAf52YqtASUs= -cloud.google.com/go/apigeeregistry v0.9.2 h1:fC3ZXEk2QsBxUlZZDZpbBGXC/ZQglCBmHDGgY5aNipg= -cloud.google.com/go/apigeeregistry v0.9.2/go.mod h1:A5n/DwpG5NaP2fcLYGiFA9QfzpQhPRFNATO1gie8KM8= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0 h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1 h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/appengine v1.8.1 h1:J+aaUZ6IbTpBegXbmEsh8qZZy864ZVnOoWyfa1XSNbI= -cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= -cloud.google.com/go/appengine v1.8.4 h1:Qub3fqR7iA1daJWdzjp/Q0Jz0fUG0JbMc7Ui4E9IX/E= -cloud.google.com/go/appengine v1.8.5 h1:l2SviT44zWQiOv8bPoMBzW0vOcMO22iO0s+nVtVhdts= -cloud.google.com/go/appengine v1.8.5/go.mod h1:uHBgNoGLTS5di7BvU25NFDuKa82v0qQLjyMJLuPQrVo= -cloud.google.com/go/appengine v1.9.2 h1:pxAQ//FsyEQsaF9HJduPCOEvj9GV4fvnLARGz1+KDzM= -cloud.google.com/go/appengine v1.9.2/go.mod h1:bK4dvmMG6b5Tem2JFZcjvHdxco9g6t1pwd3y/1qr+3s= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1 h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/area120 v0.8.1 h1:wiOq3KDpdqXmaHzvZwKdpoM+3lDcqsI2Lwhyac7stss= -cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= -cloud.google.com/go/area120 v0.8.4 h1:YnSO8m02pOIo6AEOgiOoUDVbw4pf+bg2KLHi4rky320= -cloud.google.com/go/area120 v0.8.5 h1:vTs08KPLN/iMzTbxpu5ciL06KcsrVPMjz4IwcQyZ4uY= -cloud.google.com/go/area120 v0.8.5/go.mod h1:BcoFCbDLZjsfe4EkCnEq1LKvHSK0Ew/zk5UFu6GMyA0= -cloud.google.com/go/area120 v0.9.2 h1:LODm6TjW27/LJ4z4fBNJHRb+tlvy0gSu6Vb8j2lfluY= -cloud.google.com/go/area120 v0.9.2/go.mod h1:Ar/KPx51UbrTWGVGgGzFnT7hFYQuk/0VOXkvHdTbQMI= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0 h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/artifactregistry v1.14.1 h1:k6hNqab2CubhWlGcSzunJ7kfxC7UzpAfQ1UPb9PDCKI= -cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= -cloud.google.com/go/artifactregistry v1.14.6 h1:/hQaadYytMdA5zBh+RciIrXZQBWK4vN7EUsrQHG+/t8= -cloud.google.com/go/artifactregistry v1.14.7 h1:W9sVlyb1VRcUf83w7aM3yMsnp4HS4PoyGqYQNG0O5lI= -cloud.google.com/go/artifactregistry v1.14.7/go.mod h1:0AUKhzWQzfmeTvT4SjfI4zjot72EMfrkvL9g9aRjnnM= -cloud.google.com/go/artifactregistry v1.16.0 h1:BZpz0x8HCG7hwTkD+GlUwPQVFGOo9w84t8kxQwwc0DA= -cloud.google.com/go/artifactregistry v1.16.0/go.mod h1:LunXo4u2rFtvJjrGjO0JS+Gs9Eco2xbZU6JVJ4+T8Sk= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0 h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/asset v1.14.1 h1:vlHdznX70eYW4V1y1PxocvF6tEwxJTTarwIGwOhFF3U= -cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= -cloud.google.com/go/asset v1.15.3 h1:uI8Bdm81s0esVWbWrTHcjFDFKNOa9aB7rI1vud1hO84= -cloud.google.com/go/asset v1.17.1/go.mod h1:byvDw36UME5AzGNK7o4JnOnINkwOZ1yRrGrKIahHrng= -cloud.google.com/go/asset v1.17.2 h1:xgFnBP3luSbUcC9RWJvb3Zkt+y/wW6PKwPHr3ssnIP8= -cloud.google.com/go/asset v1.17.2/go.mod h1:SVbzde67ehddSoKf5uebOD1sYw8Ab/jD/9EIeWg99q4= -cloud.google.com/go/asset v1.20.3 h1:/jQBAkZVUbsIczRepDkwaf/K5NcRYvQ6MBiWg5i20fU= -cloud.google.com/go/asset v1.20.3/go.mod h1:797WxTDwdnFAJzbjZ5zc+P5iwqXc13yO9DHhmS6wl+o= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0 h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/assuredworkloads v1.11.1 h1:yaO0kwS+SnhVSTF7BqTyVGt3DTocI6Jqo+S3hHmCwNk= -cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/assuredworkloads v1.11.4 h1:FsLSkmYYeNuzDm8L4YPfLWV+lQaUrJmH5OuD37t1k20= -cloud.google.com/go/assuredworkloads v1.11.5 h1:gCrN3IyvqY3cP0wh2h43d99CgH3G+WYs9CeuFVKChR8= -cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= -cloud.google.com/go/assuredworkloads v1.12.2 h1:6Y6a4V7CD50qtjvayhu7f5o35UFJP8ade7IbHNfdQEc= -cloud.google.com/go/assuredworkloads v1.12.2/go.mod h1:/WeRr/q+6EQYgnoYrqCVgw7boMoDfjXZZev3iJxs2Iw= -cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= -cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= -cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= -cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0 h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/automl v1.13.1 h1:iP9iQurb0qbz+YOOMfKSEjhONA/WcoOIjt6/m+6pIgo= -cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= -cloud.google.com/go/automl v1.13.4 h1:i9tOKXX+1gE7+rHpWKjiuPfGBVIYoWvLNIGpWgPtF58= -cloud.google.com/go/automl v1.13.5 h1:ijiJy9sYWh75WrqImXsfWc1e3HR3iO+ef9fvW03Ig/4= -cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y= -cloud.google.com/go/automl v1.14.2 h1:RzR5Nx78iaF2FNAfaaQ/7o2b4VuQ17YbOaeK/DLYSW4= -cloud.google.com/go/automl v1.14.2/go.mod h1:mIat+Mf77W30eWQ/vrhjXsXaRh8Qfu4WiymR0hR6Uxk= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0 h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/baremetalsolution v1.2.0 h1:3zztyuQHjfU0C0qEsI9LkC3kf5/TQQ3jUJhbmetUoRA= -cloud.google.com/go/baremetalsolution v1.2.0/go.mod h1:68wi9AwPYkEWIUT4SvSGS9UJwKzNpshjHsH4lzk8iOw= -cloud.google.com/go/baremetalsolution v1.2.3 h1:oQiFYYCe0vwp7J8ZmF6siVKEumWtiPFJMJcGuyDVRUk= -cloud.google.com/go/baremetalsolution v1.2.4 h1:LFydisRmS7hQk9P/YhekwuZGqb45TW4QavcrMToWo5A= -cloud.google.com/go/baremetalsolution v1.2.4/go.mod h1:BHCmxgpevw9IEryE99HbYEfxXkAEA3hkMJbYYsHtIuY= -cloud.google.com/go/baremetalsolution v1.3.2 h1:rhawlI+9gy/i1ZQbN/qL6FXHGXusWbfr6UoQdcCpybw= -cloud.google.com/go/baremetalsolution v1.3.2/go.mod h1:3+wqVRstRREJV/puwaKAH3Pnn7ByreZG2aFRsavnoBQ= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0 h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/batch v1.4.1 h1:/4ADpZKoKH300HN2SB6aI7lXX/0hnnbR74wxjLHkyQo= -cloud.google.com/go/batch v1.4.1/go.mod h1:KdBmDD61K0ovcxoRHGrN6GmOBWeAOyCgKD0Mugx4Fkk= -cloud.google.com/go/batch v1.6.3 h1:mPiIH20a5NU02rucbAmLeO4sLPO9hrTK0BLjdHyW8xw= -cloud.google.com/go/batch v1.8.0 h1:2HK4JerwVaIcCh/lJiHwh6+uswPthiMMWhiSWLELayk= -cloud.google.com/go/batch v1.8.0/go.mod h1:k8V7f6VE2Suc0zUM4WtoibNrA6D3dqBpB+++e3vSGYc= -cloud.google.com/go/batch v1.11.2 h1:OVhgpMMJc+mrFw51R3C06JKC0D6u125RlEBULpg78No= -cloud.google.com/go/batch v1.11.2/go.mod h1:ehsVs8Y86Q4K+qhEStxICqQnNqH8cqgpCxx89cmU5h4= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0 h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/beyondcorp v1.0.0 h1:VPg+fZXULQjs8LiMeWdLaB5oe8G9sEoZ0I0j6IMiG1Q= -cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/beyondcorp v1.0.3 h1:VXf9SnrnSmj2BF2cHkoTHvOUp8gjsz1KJFOMW7czdsY= -cloud.google.com/go/beyondcorp v1.0.4 h1:qs0J0O9Ol2h1yA0AU+r7l3hOCPzs2MjE1d6d/kaHIKo= -cloud.google.com/go/beyondcorp v1.0.4/go.mod h1:Gx8/Rk2MxrvWfn4WIhHIG1NV7IBfg14pTKv1+EArVcc= -cloud.google.com/go/beyondcorp v1.1.2 h1:hzKZf9ScvqTWqR8xGKVvD35ScQuxbMySELvJ0OW1usI= -cloud.google.com/go/beyondcorp v1.1.2/go.mod h1:q6YWSkEsSZTU2WDt1qtz6P5yfv79wgktGtNbd0FJTLI= -cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0 h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/bigquery v1.55.0 h1:hs44Xxov3XLWQiCx2J8lK5U/ihLqnpm4RVVl5fdtLLI= -cloud.google.com/go/bigquery v1.55.0/go.mod h1:9Y5I3PN9kQWuid6183JFhOGOW3GcirA5LpsKCUn+2ec= -cloud.google.com/go/bigquery v1.57.1 h1:FiULdbbzUxWD0Y4ZGPSVCDLvqRSyCIO6zKV7E2nf5uA= -cloud.google.com/go/bigquery v1.58.0/go.mod h1:0eh4mWNY0KrBTjUzLjoYImapGORq9gEPT7MWjCy9lik= -cloud.google.com/go/bigquery v1.59.1 h1:CpT+/njKuKT3CEmswm6IbhNu9u35zt5dO4yPDLW+nG4= -cloud.google.com/go/bigquery v1.59.1/go.mod h1:VP1UJYgevyTwsV7desjzNzDND5p6hZB+Z8gZJN1GQUc= -cloud.google.com/go/bigquery v1.64.0 h1:vSSZisNyhr2ioJE1OuYBQrnrpB7pIhRQm4jfjc7E/js= -cloud.google.com/go/bigquery v1.64.0/go.mod h1:gy8Ooz6HF7QmA+TRtX8tZmXBKH5mCFBwUApGAb3zI7Y= -cloud.google.com/go/bigtable v1.33.0 h1:2BDaWLRAwXO14DJL/u8crbV2oUbMZkIa2eGq8Yao1bk= -cloud.google.com/go/bigtable v1.33.0/go.mod h1:HtpnH4g25VT1pejHRtInlFPnN5sjTxbQlsYBjh9t5l0= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0 h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/billing v1.17.0 h1:CpagWXb/+QNye+vouomndbc4Gsr0uo+AGR24V16uk8Q= -cloud.google.com/go/billing v1.17.0/go.mod h1:Z9+vZXEq+HwH7bhJkyI4OQcR6TSbeMrjlpEjO2vzY64= -cloud.google.com/go/billing v1.17.4 h1:77/4kCqzH6Ou5CCDzNmqmboE+WvbwFBJmw1QZQz19AI= -cloud.google.com/go/billing v1.18.2 h1:oWUEQvuC4JvtnqLZ35zgzdbuHt4Itbftvzbe6aEyFdE= -cloud.google.com/go/billing v1.18.2/go.mod h1:PPIwVsOOQ7xzbADCwNe8nvK776QpfrOAUkvKjCUcpSE= -cloud.google.com/go/billing v1.19.2 h1:shcyz1UkrUxbPsqHL6L84ZdtBZ7yocaFFCxMInTsrNo= -cloud.google.com/go/billing v1.19.2/go.mod h1:AAtih/X2nka5mug6jTAq8jfh1nPye0OjkHbZEZgU59c= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0 h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/binaryauthorization v1.7.0 h1:7L6uUWo/xNCfdVNnnzh2M4x5YA732YPgqRdCG8aKVAU= -cloud.google.com/go/binaryauthorization v1.7.0/go.mod h1:Zn+S6QqTMn6odcMU1zDZCJxPjU2tZPV1oDl45lWY154= -cloud.google.com/go/binaryauthorization v1.7.3 h1:3R6WYn1JKIaVicBmo18jXubu7xh4mMkmbIgsTXk0cBA= -cloud.google.com/go/binaryauthorization v1.8.1 h1:1jcyh2uIUwSZkJ/JmL8kd5SUkL/Krbv8zmYLEbAz6kY= -cloud.google.com/go/binaryauthorization v1.8.1/go.mod h1:1HVRyBerREA/nhI7yLang4Zn7vfNVA3okoAR9qYQJAQ= -cloud.google.com/go/binaryauthorization v1.9.2 h1:zZX4cvtYSXc5ogOar1w5KA1BLz3j464RPSaR/HhroJ8= -cloud.google.com/go/binaryauthorization v1.9.2/go.mod h1:T4nOcRWi2WX4bjfSRXJkUnpliVIqjP38V88Z10OvEv4= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0 h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/certificatemanager v1.7.1 h1:uKsohpE0hiobx1Eak9jNcPCznwfB6gvyQCcS28Ah9E8= -cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= -cloud.google.com/go/certificatemanager v1.7.4 h1:5YMQ3Q+dqGpwUZ9X5sipsOQ1fLPsxod9HNq0+nrqc6I= -cloud.google.com/go/certificatemanager v1.7.5 h1:UMBr/twXvH3jcT5J5/YjRxf2tvwTYIfrpemTebe0txc= -cloud.google.com/go/certificatemanager v1.7.5/go.mod h1:uX+v7kWqy0Y3NG/ZhNvffh0kuqkKZIXdvlZRO7z0VtM= -cloud.google.com/go/certificatemanager v1.9.2 h1:/lO1ejN415kRaiO6DNNCHj0UvQujKP714q3l8gp4lsY= -cloud.google.com/go/certificatemanager v1.9.2/go.mod h1:PqW+fNSav5Xz8bvUnJpATIRo1aaABP4mUg/7XIeAn6c= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0 h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/channel v1.17.0 h1:Hy2EaOiOB7BS1IJmg2lLilEo8uMfFWTy7RgjTzbUqjM= -cloud.google.com/go/channel v1.17.0/go.mod h1:RpbhJsGi/lXWAUM1eF4IbQGbsfVlg2o8Iiy2/YLfVT0= -cloud.google.com/go/channel v1.17.3 h1:Rd4+fBrjiN6tZ4TR8R/38elkyEkz6oogGDr7jDyjmMY= -cloud.google.com/go/channel v1.17.5 h1:/omiBnyFjm4S1ETHoOmJbL7LH7Ljcei4rYG6Sj3hc80= -cloud.google.com/go/channel v1.17.5/go.mod h1:FlpaOSINDAXgEext0KMaBq/vwpLMkkPAw9b2mApQeHc= -cloud.google.com/go/channel v1.19.1 h1:l4XcnfzJ5UGmqZQls0atcpD6ERDps4PLd5hXSyTWFv0= -cloud.google.com/go/channel v1.19.1/go.mod h1:ungpP46l6XUeuefbA/XWpWWnAY3897CSRPXUbDstwUo= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0 h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/cloudbuild v1.14.0 h1:YTMxmFra7eIjKFgnyQUxOwWNseNqeO38kGh7thy7v4s= -cloud.google.com/go/cloudbuild v1.14.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/cloudbuild v1.14.3 h1:hP6LDes9iqeppgGbmCkB3C3MvS12gJe5i4ZGtnnIO5c= -cloud.google.com/go/cloudbuild v1.14.3/go.mod h1:eIXYWmRt3UtggLnFGx4JvXcMj4kShhVzGndL1LwleEM= -cloud.google.com/go/cloudbuild v1.15.0 h1:9IHfEMWdCklJ1cwouoiQrnxmP0q3pH7JUt8Hqx4Qbck= -cloud.google.com/go/cloudbuild v1.15.1 h1:ZB6oOmJo+MTov9n629fiCrO9YZPOg25FZvQ7gIHu5ng= -cloud.google.com/go/cloudbuild v1.15.1/go.mod h1:gIofXZSu+XD2Uy+qkOrGKEx45zd7s28u/k8f99qKals= -cloud.google.com/go/cloudbuild v1.19.0 h1:Uo0bL251yvyWsNtO3Og9m5Z4S48cgGf3IUX7xzOcl8s= -cloud.google.com/go/cloudbuild v1.19.0/go.mod h1:ZGRqbNMrVGhknIIjwASa6MqoRTOpXIVMSI+Ew5DMPuY= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0 h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/clouddms v1.7.0 h1:vTcaFaFZTZZ11gXB6aZHdAx+zn30P8YJw4X/S3NC+VQ= -cloud.google.com/go/clouddms v1.7.0/go.mod h1:MW1dC6SOtI/tPNCciTsXtsGNEM0i0OccykPvv3hiYeM= -cloud.google.com/go/clouddms v1.7.3 h1:xe/wJKz55VO1+L891a1EG9lVUgfHr9Ju/I3xh1nwF84= -cloud.google.com/go/clouddms v1.7.4 h1:Sr0Zo5EAcPQiCBgHWICg3VGkcdS/LLP1d9SR7qQBM/s= -cloud.google.com/go/clouddms v1.7.4/go.mod h1:RdrVqoFG9RWI5AvZ81SxJ/xvxPdtcRhFotwdE79DieY= -cloud.google.com/go/clouddms v1.8.2 h1:U53ztLRgTkclaxgmBBles+tv+nNcZ5fhbRbw3b2axFw= -cloud.google.com/go/clouddms v1.8.2/go.mod h1:pe+JSp12u4mYOkwXpSMouyCCuQHL3a6xvWH2FgOcAt4= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0 h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/cloudtasks v1.12.1 h1:cMh9Q6dkvh+Ry5LAPbD/U2aw6KAqdiU6FttwhbTo69w= -cloud.google.com/go/cloudtasks v1.12.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/cloudtasks v1.12.4 h1:5xXuFfAjg0Z5Wb81j2GAbB3e0bwroCeSF+5jBn/L650= -cloud.google.com/go/cloudtasks v1.12.6 h1:EUt1hIZ9bLv8Iz9yWaCrqgMnIU+Tdh0yXM1MMVGhjfE= -cloud.google.com/go/cloudtasks v1.12.6/go.mod h1:b7c7fe4+TJsFZfDyzO51F7cjq7HLUlRi/KZQLQjDsaY= -cloud.google.com/go/cloudtasks v1.13.2 h1:x6Qw5JyNbH3reL0arUtlYf77kK6OVjZZ//8JCvUkLro= -cloud.google.com/go/cloudtasks v1.13.2/go.mod h1:2pyE4Lhm7xY8GqbZKLnYk7eeuh8L0JwAvXx1ecKxYu8= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= -cloud.google.com/go/compute v1.23.2/go.mod h1:JJ0atRC0J/oWYiiVBmsSsrRnh92DhZPG4hFDcR04Rns= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= -cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= -cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= -cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= -cloud.google.com/go/compute v1.29.0 h1:Lph6d8oPi38NHkOr6S55Nus/Pbbcp37m/J0ohgKAefs= -cloud.google.com/go/compute v1.29.0/go.mod h1:HFlsDurE5DpQZClAGf/cYh+gxssMhBxBovZDYkEn/Og= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0 h1:nBbNSZyDpkNlo3DepaaLKVuO7ClyifSAmNloSCZrHnQ= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0 h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/contactcenterinsights v1.10.0 h1:YR2aPedGVQPpFBZXJnPkqRj8M//8veIZZH5ZvICoXnI= -cloud.google.com/go/contactcenterinsights v1.10.0/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/contactcenterinsights v1.11.3 h1:Ui14kRKgQ3mVrMRkiBNzjdJIfFAN2qqiu9993ec9+jw= -cloud.google.com/go/contactcenterinsights v1.11.3/go.mod h1:HHX5wrz5LHVAwfI2smIotQG9x8Qd6gYilaHcLLLmNis= -cloud.google.com/go/contactcenterinsights v1.12.0 h1:wP41IUA4ucMVooj/TP53jd7vbNjWrDkAPOeulVJGT5U= -cloud.google.com/go/contactcenterinsights v1.13.0 h1:6Vs/YnDG5STGjlWMEjN/xtmft7MrOTOnOZYUZtGTx0w= -cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= -cloud.google.com/go/contactcenterinsights v1.15.1 h1:cR/gQMweaG8RIWAlS5Jo1ARi8LUVQJ51t84EUefHeZ8= -cloud.google.com/go/contactcenterinsights v1.15.1/go.mod h1:cFGxDVm/OwEVAHbU9UO4xQCtQFn0RZSrSUcF/oJ0Bbs= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0 h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/container v1.26.0 h1:SszQdI0qlyKsImz8/l26rpTZMyqvaH9yfua7rirDZvY= -cloud.google.com/go/container v1.26.0/go.mod h1:YJCmRet6+6jnYYRS000T6k0D0xUXQgBSaJ7VwI8FBj4= -cloud.google.com/go/container v1.27.1 h1:ZfLRiFM9ddFE92SlA28rknI6YJMz5Z5huAQK+FKWxIQ= -cloud.google.com/go/container v1.27.1/go.mod h1:b1A1gJeTBXVLQ6GGw9/9M4FG94BEGsqJ5+t4d/3N7O4= -cloud.google.com/go/container v1.28.0 h1:/o82CFWXIYnT9p/07SnRgybqL3Pmmu86jYIlzlJVUBY= -cloud.google.com/go/container v1.30.1/go.mod h1:vkbfX0EnAKL/vgVECs5BZn24e1cJROzgszJirRKQ4Bg= -cloud.google.com/go/container v1.31.0 h1:MAaNH7VRNPWEhvqOypq2j+7ONJKrKzon4v9nS3nLZe0= -cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA= -cloud.google.com/go/container v1.42.0 h1:sH9Hj9SoLeP+uKvLXc/04nWyWDiMo4Q85xfb1Nl5sAg= -cloud.google.com/go/container v1.42.0/go.mod h1:YL6lDgCUi3frIWNIFU9qrmF7/6K1EYrtspmFTyyqJ+k= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0 h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/containeranalysis v0.11.0 h1:/EsoP+UTIjvl4yqrLA4WgUG83kwQhqZmbXEfqirT2LM= -cloud.google.com/go/containeranalysis v0.11.0/go.mod h1:4n2e99ZwpGxpNcz+YsFT1dfOHPQFGcAC8FN2M2/ne/U= -cloud.google.com/go/containeranalysis v0.11.3 h1:5rhYLX+3a01drpREqBZVXR9YmWH45RnML++8NsCtuD8= -cloud.google.com/go/containeranalysis v0.11.4 h1:doJ0M1ljS4hS0D2UbHywlHGwB7sQLNrt9vFk9Zyi7vY= -cloud.google.com/go/containeranalysis v0.11.4/go.mod h1:cVZT7rXYBS9NG1rhQbWL9pWbXCKHWJPYraE8/FTSYPE= -cloud.google.com/go/containeranalysis v0.13.2 h1:AG2gOcfZJFRiz+3SZCPnxU+gwbzKe++QSX/ej71Lom8= -cloud.google.com/go/containeranalysis v0.13.2/go.mod h1:AiKvXJkc3HiqkHzVIt6s5M81wk+q7SNffc6ZlkTDgiE= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0 h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/datacatalog v1.17.1 h1:qGWrlYvWtK+8jD1jhwq5BsGoSr7S4/LOroV7LwXi00g= -cloud.google.com/go/datacatalog v1.17.1/go.mod h1:nCSYFHgtxh2MiEktWIz71s/X+7ds/UT9kp0PC7waCzE= -cloud.google.com/go/datacatalog v1.18.3 h1:zmdxP6nOjN5Qb1rtu9h4kbEVwerQ6Oshf+t747QJUew= -cloud.google.com/go/datacatalog v1.18.3/go.mod h1:5FR6ZIF8RZrtml0VUao22FxhdjkoG+a0866rEnObryM= -cloud.google.com/go/datacatalog v1.19.0 h1:rbYNmHwvAOOwnW2FPXYkaK3Mf1MmGqRzK0mMiIEyLdo= -cloud.google.com/go/datacatalog v1.19.3 h1:A0vKYCQdxQuV4Pi0LL9p39Vwvg4jH5yYveMv50gU5Tw= -cloud.google.com/go/datacatalog v1.19.3/go.mod h1:ra8V3UAsciBpJKQ+z9Whkxzxv7jmQg1hfODr3N3YPJ4= -cloud.google.com/go/datacatalog v1.23.0 h1:9F2zIbWNNmtrSkPIyGRQNsIugG5VgVVFip6+tXSdWLg= -cloud.google.com/go/datacatalog v1.23.0/go.mod h1:9Wamq8TDfL2680Sav7q3zEhBJSPBrDxJU8WtPJ25dBM= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0 h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataflow v0.9.1 h1:VzG2tqsk/HbmOtq/XSfdF4cBvUWRK+S+oL9k4eWkENQ= -cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= -cloud.google.com/go/dataflow v0.9.4 h1:7VmCNWcPJBS/srN2QnStTB6nu4Eb5TMcpkmtaPVhRt4= -cloud.google.com/go/dataflow v0.9.5 h1:RYHtcPhmE664+F0Je46p+NvFbG8z//KCXp+uEqB4jZU= -cloud.google.com/go/dataflow v0.9.5/go.mod h1:udl6oi8pfUHnL0z6UN9Lf9chGqzDMVqcYTcZ1aPnCZQ= -cloud.google.com/go/dataflow v0.10.2 h1:o9P5/zR2mOYJmCnfp9/7RprKFZCwmSu3TvemQSmCaFM= -cloud.google.com/go/dataflow v0.10.2/go.mod h1:+HIb4HJxDCZYuCqDGnBHZEglh5I0edi/mLgVbxDf0Ag= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0 h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/dataform v0.8.1 h1:xcWso0hKOoxeW72AjBSIp/UfkvpqHNzzS0/oygHlcqY= -cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= -cloud.google.com/go/dataform v0.9.1 h1:jV+EsDamGX6cE127+QAcCR/lergVeeZdEQ6DdrxW3sQ= -cloud.google.com/go/dataform v0.9.2 h1:5e4eqGrd0iDTCg4Q+VlAao5j2naKAA7xRurNtwmUknU= -cloud.google.com/go/dataform v0.9.2/go.mod h1:S8cQUwPNWXo7m/g3DhWHsLBoufRNn9EgFrMgne2j7cI= -cloud.google.com/go/dataform v0.10.2 h1:t16DoejuOHoxJR88qrpdmFFlCXA9+x5PKrqI9qiDYz0= -cloud.google.com/go/dataform v0.10.2/go.mod h1:oZHwMBxG6jGZCVZqqMx+XWXK+dA/ooyYiyeRbUxI15M= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0 h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datafusion v1.7.1 h1:eX9CZoyhKQW6g1Xj7+RONeDj1mV8KQDKEB9KLELX9/8= -cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= -cloud.google.com/go/datafusion v1.7.4 h1:Q90alBEYlMi66zL5gMSGQHfbZLB55mOAg03DhwTTfsk= -cloud.google.com/go/datafusion v1.7.5 h1:HQ/BUOP8OIGJxuztpYvNvlb+/U+/Bfs9SO8tQbh61fk= -cloud.google.com/go/datafusion v1.7.5/go.mod h1:bYH53Oa5UiqahfbNK9YuYKteeD4RbQSNMx7JF7peGHc= -cloud.google.com/go/datafusion v1.8.2 h1:RPoHvIeXexXwlWhEU6DNgrYCh+C+FR2EXbrnMs2ptpI= -cloud.google.com/go/datafusion v1.8.2/go.mod h1:XernijudKtVG/VEvxtLv08COyVuiYPraSxm+8hd4zXA= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0 h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/datalabeling v0.8.1 h1:zxsCD/BLKXhNuRssen8lVXChUj8VxF3ofN06JfdWOXw= -cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= -cloud.google.com/go/datalabeling v0.8.4 h1:zrq4uMmunf2KFDl/7dS6iCDBBAxBnKVDyw6+ajz3yu0= -cloud.google.com/go/datalabeling v0.8.5 h1:GpIFRdm0qIZNsxqURFJwHt0ZBJZ0nF/mUVEigR7PH/8= -cloud.google.com/go/datalabeling v0.8.5/go.mod h1:IABB2lxQnkdUbMnQaOl2prCOfms20mcPxDBm36lps+s= -cloud.google.com/go/datalabeling v0.9.2 h1:UesbU2kYIUWhHUcnFS86ANPbugEq98X9k1whTNcenlc= -cloud.google.com/go/datalabeling v0.9.2/go.mod h1:8me7cCxwV/mZgYWtRAd3oRVGFD6UyT7hjMi+4GRyPpg= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0 h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataplex v1.9.1 h1:wqPAP1vRskOoWwNka1yey2wxxCrxRrcxJf78MyFvrbs= -cloud.google.com/go/dataplex v1.9.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataplex v1.11.1 h1:+malGTMnHubsSi0D6dbr3aqp86dKs0t4yAdmxKZGUm4= -cloud.google.com/go/dataplex v1.11.1/go.mod h1:mHJYQQ2VEJHsyoC0OdNyy988DvEbPhqFs5OOLffLX0c= -cloud.google.com/go/dataplex v1.11.2 h1:AfFFR15Ifh4U+Me1IBztrSd5CrasTODzy3x8KtDyHdc= -cloud.google.com/go/dataplex v1.14.1/go.mod h1:bWxQAbg6Smg+sca2+Ex7s8D9a5qU6xfXtwmq4BVReps= -cloud.google.com/go/dataplex v1.14.2 h1:fxIfdU8fxzR3clhOoNI7XFppvAmndxDu1AMH+qX9WKQ= -cloud.google.com/go/dataplex v1.14.2/go.mod h1:0oGOSFlEKef1cQeAHXy4GZPB/Ife0fz/PxBf+ZymA2U= -cloud.google.com/go/dataplex v1.19.2 h1:R2xnsZnuWpHi2NmBR0e43GZk2IZcQ1AFEAo1fUI0xsw= -cloud.google.com/go/dataplex v1.19.2/go.mod h1:vsxxdF5dgk3hX8Ens9m2/pMNhQZklUhSgqTghZtF1v4= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataproc/v2 v2.2.0 h1:jKijbdsERm2hy/5dFl/LeQN+7CNssLdGXQYBMvMH/M4= -cloud.google.com/go/dataproc/v2 v2.2.0/go.mod h1:lZR7AQtwZPvmINx5J87DSOOpTfof9LVZju6/Qo4lmcY= -cloud.google.com/go/dataproc/v2 v2.2.3 h1:snv4EQfh1BfQ/HZS2MGbOqCgwEzYE/j6f30XFOTsgXg= -cloud.google.com/go/dataproc/v2 v2.2.3/go.mod h1:G5R6GBc9r36SXv/RtZIVfB8SipI+xVn0bX5SxUzVYbY= -cloud.google.com/go/dataproc/v2 v2.3.0 h1:tTVP9tTxmc8fixxOd/8s6Q6Pz/+yzn7r7XdZHretQH0= -cloud.google.com/go/dataproc/v2 v2.4.0 h1:/u81Fd+BvCLp+xjctI1DiWVJn6cn9/s3Akc8xPH02yk= -cloud.google.com/go/dataproc/v2 v2.4.0/go.mod h1:3B1Ht2aRB8VZIteGxQS/iNSJGzt9+CA0WGnDVMEm7Z4= -cloud.google.com/go/dataproc/v2 v2.10.0 h1:B0b7eLRXzFTzb4UaxkGGidIF23l/Xpyce28m1Q0cHmU= -cloud.google.com/go/dataproc/v2 v2.10.0/go.mod h1:HD16lk4rv2zHFhbm8gGOtrRaFohMDr9f0lAUMLmg1PM= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0 h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/dataqna v0.8.1 h1:ITpUJep04hC9V7C+gcK390HO++xesQFSUJ7S4nSnF3U= -cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= -cloud.google.com/go/dataqna v0.8.4 h1:NJnu1kAPamZDs/if3bJ3+Wb6tjADHKL83NUWsaIp2zg= -cloud.google.com/go/dataqna v0.8.5 h1:9ybXs3nr9BzxSGC04SsvtuXaHY0qmJSLIpIAbZo9GqQ= -cloud.google.com/go/dataqna v0.8.5/go.mod h1:vgihg1mz6n7pb5q2YJF7KlXve6tCglInd6XO0JGOlWM= -cloud.google.com/go/dataqna v0.9.2 h1:hrEcid5jK5fEdlYZ0eS8HJoq+ZCTRWSV7Av42V/G994= -cloud.google.com/go/dataqna v0.9.2/go.mod h1:WCJ7pwD0Mi+4pIzFQ+b2Zqy5DcExycNKHuB+VURPPgs= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0 h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastore v1.14.0 h1:Mq0ApTRdLW3/dyiw+DkjTk0+iGIUvkbzaC8sfPwWTH4= -cloud.google.com/go/datastore v1.14.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= -cloud.google.com/go/datastore v1.15.0 h1:0P9WcsQeTWjuD1H14JIY7XQscIPQ4Laje8ti96IC5vg= -cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= -cloud.google.com/go/datastore v1.20.0 h1:NNpXoyEqIJmZFc0ACcwBEaXnmscUpcG4NkKnbCePmiM= -cloud.google.com/go/datastore v1.20.0/go.mod h1:uFo3e+aEpRfHgtp5pp0+6M0o147KoPaYNaPAKpfh8Ew= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0 h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/datastream v1.10.0 h1:ra/+jMv36zTAGPfi8TRne1hXme+UsKtdcK4j6bnqQiw= -cloud.google.com/go/datastream v1.10.0/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/datastream v1.10.3 h1:Z2sKPIB7bT2kMW5Uhxy44ZgdJzxzE5uKjavoW+EuHEE= -cloud.google.com/go/datastream v1.10.4 h1:o1QDKMo/hk0FN7vhoUQURREuA0rgKmnYapB+1M+7Qz4= -cloud.google.com/go/datastream v1.10.4/go.mod h1:7kRxPdxZxhPg3MFeCSulmAJnil8NJGGvSNdn4p1sRZo= -cloud.google.com/go/datastream v1.11.2 h1:vgtrwwPfY7JFEDD0VARJK4qyiApnFnPkFRQVuczYb/w= -cloud.google.com/go/datastream v1.11.2/go.mod h1:RnFWa5zwR5SzHxeZGJOlQ4HKBQPcjGfD219Qy0qfh2k= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0 h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/deploy v1.13.0 h1:A+w/xpWgz99EYzB6e31gMGAI/P5jTZ2UO7veQK5jQ8o= -cloud.google.com/go/deploy v1.13.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/deploy v1.14.2 h1:OWVwtGy+QeQGPT3yc8bJu6yANoPFpXniCgl7bJu5u88= -cloud.google.com/go/deploy v1.14.2/go.mod h1:e5XOUI5D+YGldyLNZ21wbp9S8otJbBE4i88PtO9x/2g= -cloud.google.com/go/deploy v1.15.0 h1:ZdmYzRMTGkVyP1nXEUat9FpbJGJemDcNcx82RSSOElc= -cloud.google.com/go/deploy v1.17.1 h1:m27Ojwj03gvpJqCbodLYiVmE9x4/LrHGGMjzc0LBfM4= -cloud.google.com/go/deploy v1.17.1/go.mod h1:SXQyfsXrk0fBmgBHRzBjQbZhMfKZ3hMQBw5ym7MN/50= -cloud.google.com/go/deploy v1.25.0 h1:nYLFG2TSsYMJuengVru5P8iWnA5mNA4rKFV5YoOWQ3M= -cloud.google.com/go/deploy v1.25.0/go.mod h1:h9uVCWxSDanXUereI5WR+vlZdbPJ6XGy+gcfC25v5rM= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0 h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dialogflow v1.43.0 h1:0hBV5ipVbhYNKCyiBoM47bUt+43Kd8eWXhBr+pwUSTw= -cloud.google.com/go/dialogflow v1.43.0/go.mod h1:pDUJdi4elL0MFmt1REMvFkdsUTYSHq+rTCS8wg0S3+M= -cloud.google.com/go/dialogflow v1.44.3 h1:cK/f88KX+YVR4tLH4clMQlvrLWD2qmKJQziusjGPjmc= -cloud.google.com/go/dialogflow v1.48.2/go.mod h1:7A2oDf6JJ1/+hdpnFRfb/RjJUOh2X3rhIa5P8wQSEX4= -cloud.google.com/go/dialogflow v1.49.0 h1:KqG0oxGE71qo0lRVyAoeBozefCvsMfcDzDjoLYSY0F4= -cloud.google.com/go/dialogflow v1.49.0/go.mod h1:dhVrXKETtdPlpPhE7+2/k4Z8FRNUp6kMV3EW3oz/fe0= -cloud.google.com/go/dialogflow v1.60.0 h1:H+Q1SUeVU2La0Y0ZGEaKkhEXg3bj9Ceg5YKcMbyNOEc= -cloud.google.com/go/dialogflow v1.60.0/go.mod h1:PjsrI+d2FI4BlGThxL0+Rua/g9vLI+2A1KL7s/Vo3pY= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0 h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/dlp v1.10.1 h1:tF3wsJ2QulRhRLWPzWVkeDz3FkOGVoMl6cmDUHtfYxw= -cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= -cloud.google.com/go/dlp v1.11.1 h1:OFlXedmPP/5//X1hBEeq3D9kUVm9fb6ywYANlpv/EsQ= -cloud.google.com/go/dlp v1.11.2 h1:lTipOuJaSjlYnnotPMbEhKURLC6GzCMDDzVbJAEbmYM= -cloud.google.com/go/dlp v1.11.2/go.mod h1:9Czi+8Y/FegpWzgSfkRlyz+jwW6Te9Rv26P3UfU/h/w= -cloud.google.com/go/dlp v1.20.0 h1:Wwz1FoZp3pyrTNkS5fncaAccP/AbqzLQuN5WMi3aVYQ= -cloud.google.com/go/dlp v1.20.0/go.mod h1:nrGsA3r8s7wh2Ct9FWu69UjBObiLldNyQda2RCHgdaY= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0 h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/documentai v1.22.1 h1:cBndyac7kPWwSuhUcgdbnqzszfZ57HBEHfD33DIwsBM= -cloud.google.com/go/documentai v1.22.1/go.mod h1:LKs22aDHbJv7ufXuPypzRO7rG3ALLJxzdCXDPutw4Qc= -cloud.google.com/go/documentai v1.23.5 h1:KAlzT+q8qvRxAmhsJUvLtfFHH0PNvz3M79H6CgVBKL8= -cloud.google.com/go/documentai v1.23.8/go.mod h1:Vd/y5PosxCpUHmwC+v9arZyeMfTqBR9VIwOwIqQYYfA= -cloud.google.com/go/documentai v1.25.0 h1:lI62GMEEPO6vXJI9hj+G9WjOvnR0hEjvjokrnex4cxA= -cloud.google.com/go/documentai v1.25.0/go.mod h1:ftLnzw5VcXkLItp6pw1mFic91tMRyfv6hHEY5br4KzY= -cloud.google.com/go/documentai v1.35.0 h1:DO4ut86a+Xa0gBq7j3FZJPavnKBNoznrg44csnobqIY= -cloud.google.com/go/documentai v1.35.0/go.mod h1:ZotiWUlDE8qXSUqkJsGMQqVmfTMYATwJEYqbPXTR9kk= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0 h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/domains v0.9.1 h1:rqz6KY7mEg7Zs/69U6m6LMbB7PxFDWmT3QWNXIqhHm0= -cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= -cloud.google.com/go/domains v0.9.4 h1:ua4GvsDztZ5F3xqjeLKVRDeOvJshf5QFgWGg1CKti3A= -cloud.google.com/go/domains v0.9.5 h1:Mml/R6s3vQQvFPpi/9oX3O5dRirgjyJ8cksK8N19Y7g= -cloud.google.com/go/domains v0.9.5/go.mod h1:dBzlxgepazdFhvG7u23XMhmMKBjrkoUNaw0A8AQB55Y= -cloud.google.com/go/domains v0.10.2 h1:ekJCkuzbciXyPKkwPwvI+2Ov1GcGJtMXj/fbgilPFqg= -cloud.google.com/go/domains v0.10.2/go.mod h1:oL0Wsda9KdJvvGNsykdalHxQv4Ri0yfdDkIi3bzTUwk= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0 h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/edgecontainer v1.1.1 h1:zhHWnLzg6AqzE+I3gzJqiIwHfjEBhWctNQEzqb+FaRo= -cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= -cloud.google.com/go/edgecontainer v1.1.4 h1:Szy3Q/N6bqgQGyxqjI+6xJZbmvPvnFHp3UZr95DKcQ0= -cloud.google.com/go/edgecontainer v1.1.5 h1:tBY32km78ScpK2aOP84JoW/+wtpx5WluyPUSEE3270U= -cloud.google.com/go/edgecontainer v1.1.5/go.mod h1:rgcjrba3DEDEQAidT4yuzaKWTbkTI5zAMu3yy6ZWS0M= -cloud.google.com/go/edgecontainer v1.4.0 h1:vpKTEkQPpkl55d6aUU2rzDFvTkMUATvBXfZSlI2KMR0= -cloud.google.com/go/edgecontainer v1.4.0/go.mod h1:Hxj5saJT8LMREmAI9tbNTaBpW5loYiWFyisCjDhzu88= -cloud.google.com/go/errorreporting v0.3.0 h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/errorreporting v0.3.1 h1:E/gLk+rL7u5JZB9oq72iL1bnhVlLrnfslrgcptjJEUE= -cloud.google.com/go/errorreporting v0.3.1/go.mod h1:6xVQXU1UuntfAf+bVkFk6nld41+CPyF2NSPCyXE3Ztk= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0 h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/essentialcontacts v1.6.2 h1:OEJ0MLXXCW/tX1fkxzEZOsv/wRfyFsvDVNaHWBAvoV0= -cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= -cloud.google.com/go/essentialcontacts v1.6.5 h1:S2if6wkjR4JCEAfDtIiYtD+sTz/oXjh2NUG4cgT1y/Q= -cloud.google.com/go/essentialcontacts v1.6.6 h1:13eHn5qBnsawxI7mIrv4jRIEmQ1xg0Ztqw5ZGqtUNfA= -cloud.google.com/go/essentialcontacts v1.6.6/go.mod h1:XbqHJGaiH0v2UvtuucfOzFXN+rpL/aU5BCZLn4DYl1Q= -cloud.google.com/go/essentialcontacts v1.7.2 h1:a/reGTn7WblM5DgieiLbX6CswHgTneWrA4ZNS5E+1Bg= -cloud.google.com/go/essentialcontacts v1.7.2/go.mod h1:NoCBlOIVteJFJU+HG9dIG/Cc9kt1K9ys9mbOaGPUmPc= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0 h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/eventarc v1.13.0 h1:xIP3XZi0Xawx8DEfh++mE2lrIi5kQmCr/KcWhJ1q0J4= -cloud.google.com/go/eventarc v1.13.0/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/eventarc v1.13.3 h1:+pFmO4eu4dOVipSaFBLkmqrRYG94Xl/TQZFOeohkuqU= -cloud.google.com/go/eventarc v1.13.4 h1:ORkd6/UV5FIdA8KZQDLNZYKS7BBOrj0p01DXPmT4tE4= -cloud.google.com/go/eventarc v1.13.4/go.mod h1:zV5sFVoAa9orc/52Q+OuYUG9xL2IIZTbbuTHC6JSY8s= -cloud.google.com/go/eventarc v1.15.0 h1:IVU2EOR8P2f6N8eneuwspN122LR87v9G54B+7ihd1TY= -cloud.google.com/go/eventarc v1.15.0/go.mod h1:PAd/pPIZdJtJQFJI1yDEUms1mqohdNuM1BFEVHHlVFg= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0 h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/filestore v1.7.1 h1:Eiz8xZzMJc5ppBWkuaod/PUdUZGCFR8ku0uS+Ah2fRw= -cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= -cloud.google.com/go/filestore v1.7.4 h1:twtI5/89kf9QW7MqDic9fsUbH5ZLIDV1MVsRmu9iu2E= -cloud.google.com/go/filestore v1.7.4/go.mod h1:S5JCxIbFjeBhWMTfIYH2Jx24J6BqjwpkkPl+nBA5DlI= -cloud.google.com/go/filestore v1.8.0 h1:/+wUEGwk3x3Kxomi2cP5dsR8+SIXxo7M0THDjreFSYo= -cloud.google.com/go/filestore v1.8.1 h1:X5G4y/vrUo1B8Nsz93qSWTMAcM8LXbGUldq33OdcdCw= -cloud.google.com/go/filestore v1.8.1/go.mod h1:MbN9KcaM47DRTIuLfQhJEsjaocVebNtNQhSLhKCF5GM= -cloud.google.com/go/filestore v1.9.2 h1:DYwMNAcF5bELHHMxRdkIWWZ3XicKp+ZpEBy+c6Gt4uY= -cloud.google.com/go/filestore v1.9.2/go.mod h1:I9pM7Hoetq9a7djC1xtmtOeHSUYocna09ZP6x+PG1Xw= -cloud.google.com/go/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk= -cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= -cloud.google.com/go/firestore v1.14.0 h1:8aLcKnMPoldYU3YHgu4t2exrKhLQkqaXAGqT0ljrFVw= -cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ= -cloud.google.com/go/firestore v1.17.0 h1:iEd1LBbkDZTFsLw3sTH50eyg4qe8eoG6CjocmEXO9aQ= -cloud.google.com/go/firestore v1.17.0/go.mod h1:69uPx1papBsY8ZETooc71fOhoKkD70Q1DwMrtKuOT/Y= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0 h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/functions v1.15.1 h1:LtAyqvO1TFmNLcROzHZhV0agEJfBi+zfMZsF4RT/a7U= -cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= -cloud.google.com/go/functions v1.15.4 h1:ZjdiV3MyumRM6++1Ixu6N0VV9LAGlCX4AhW6Yjr1t+U= -cloud.google.com/go/functions v1.16.0 h1:IWVylmK5F6hJ3R5zaRW7jI5PrWhCvtBVU4axQLmXSo4= -cloud.google.com/go/functions v1.16.0/go.mod h1:nbNpfAG7SG7Duw/o1iZ6ohvL7mc6MapWQVpqtM29n8k= -cloud.google.com/go/functions v1.19.2 h1:Cu2Gj1JBBJv9gi89r8LrZNsJhGwePnhttn4Blqw/EYI= -cloud.google.com/go/functions v1.19.2/go.mod h1:SBzWwWuaFDLnUyStDAMEysVN1oA5ECLbP3/PfJ9Uk7Y= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0 h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkebackup v1.3.1 h1:Kfha8SOF2tqsu4O4jVle66mk7qNdlJ2KhL3E2YyiNZc= -cloud.google.com/go/gkebackup v1.3.1/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= -cloud.google.com/go/gkebackup v1.3.4 h1:KhnOrr9A1tXYIYeXKqCKbCI8TL2ZNGiD3dm+d7BDUBg= -cloud.google.com/go/gkebackup v1.3.5 h1:iuE8KNtTsPOc79qeWoNS8zOWoXPD9SAdOmwgxtlCmh8= -cloud.google.com/go/gkebackup v1.3.5/go.mod h1:KJ77KkNN7Wm1LdMopOelV6OodM01pMuK2/5Zt1t4Tvc= -cloud.google.com/go/gkebackup v1.6.2 h1:lWaSgjSonOXe41UhwQjts6lhDZdr5e882LNUTtnjZS0= -cloud.google.com/go/gkebackup v1.6.2/go.mod h1:WsTSWqKJkGan1pkp5dS30oxb+Eaa6cLvxEUxKTUALwk= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0 h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkeconnect v0.8.1 h1:a1ckRvVznnuvDWESM2zZDzSVFvggeBaVY5+BVB8tbT0= -cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= -cloud.google.com/go/gkeconnect v0.8.4 h1:1JLpZl31YhQDQeJ98tK6QiwTpgHFYRJwpntggpQQWis= -cloud.google.com/go/gkeconnect v0.8.5 h1:17d+ZSSXKqG/RwZCq3oFMIWLPI8Zw3b8+a9/BEVlwH0= -cloud.google.com/go/gkeconnect v0.8.5/go.mod h1:LC/rS7+CuJ5fgIbXv8tCD/mdfnlAadTaUufgOkmijuk= -cloud.google.com/go/gkeconnect v0.12.0 h1:MuA3/aIuncXkXuUDGdbT7OLnIp7xpFhciuHAnQaoQz4= -cloud.google.com/go/gkeconnect v0.12.0/go.mod h1:zn37LsFiNZxPN4iO7YbUk8l/E14pAJ7KxpoXoxt7Ly0= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0 h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkehub v0.14.1 h1:2BLSb8i+Co1P05IYCKATXy5yaaIw/ZqGvVSBTLdzCQo= -cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= -cloud.google.com/go/gkehub v0.14.4 h1:J5tYUtb3r0cl2mM7+YHvV32eL+uZQ7lONyUZnPikCEo= -cloud.google.com/go/gkehub v0.14.5 h1:RboLNFzf9wEMSo7DrKVBlf+YhK/A/jrLN454L5Tz99Q= -cloud.google.com/go/gkehub v0.14.5/go.mod h1:6bzqxM+a+vEH/h8W8ec4OJl4r36laxTs3A/fMNHJ0wA= -cloud.google.com/go/gkehub v0.15.2 h1:CR5MPEP/Ogk5IahCq3O2fKS6TJZQi8mrnrysGHCs0g8= -cloud.google.com/go/gkehub v0.15.2/go.mod h1:8YziTOpwbM8LM3r9cHaOMy2rNgJHXZCrrmGgcau9zbQ= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0 h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/gkemulticloud v1.0.0 h1:MluqhtPVZReoriP5+adGIw+ij/RIeRik8KApCW2WMTw= -cloud.google.com/go/gkemulticloud v1.0.0/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/gkemulticloud v1.0.3 h1:NmJsNX9uQ2CT78957xnjXZb26TDIMvv+d5W2vVUt0Pg= -cloud.google.com/go/gkemulticloud v1.1.1 h1:rsSZAGLhyjyE/bE2ToT5fqo1qSW7S+Ubsc9jFOcbhSI= -cloud.google.com/go/gkemulticloud v1.1.1/go.mod h1:C+a4vcHlWeEIf45IB5FFR5XGjTeYhF83+AYIpTy4i2Q= -cloud.google.com/go/gkemulticloud v1.4.1 h1:SvVD2nJTGScEDYygIQ5dI14oFYhgtJx8HazkT3aufEI= -cloud.google.com/go/gkemulticloud v1.4.1/go.mod h1:KRvPYcx53bztNwNInrezdfNF+wwUom8Y3FuJBwhvFpQ= -cloud.google.com/go/grafeas v0.2.0 h1:CYjC+xzdPvbV65gi6Dr4YowKcmLo045pm18L0DhdELM= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/grafeas v0.3.0 h1:oyTL/KjiUeBs9eYLw/40cpSZglUC+0F7X4iu/8t7NWs= -cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8= -cloud.google.com/go/grafeas v0.3.4 h1:D4x32R/cHX3MTofKwirz015uEdVk4uAxvZkZCZkOrF4= -cloud.google.com/go/grafeas v0.3.4/go.mod h1:A5m316hcG+AulafjAbPKXBO/+I5itU4LOdKO2R/uDIc= -cloud.google.com/go/grafeas v0.3.11 h1:CobnwnyeY1j1Defi5vbEircI+jfrk3ci5m004ZjiFP4= -cloud.google.com/go/grafeas v0.3.11/go.mod h1:dcQyG2+T4tBgG0MvJAh7g2wl/xHV2w+RZIqivwuLjNg= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0 h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/gsuiteaddons v1.6.1 h1:mi9jxZpzVjLQibTS/XfPZvl+Jr6D5Bs8pGqUjllRb00= -cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= -cloud.google.com/go/gsuiteaddons v1.6.4 h1:uuw2Xd37yHftViSI8J2hUcCS8S7SH3ZWH09sUDLW30Q= -cloud.google.com/go/gsuiteaddons v1.6.5 h1:CZEbaBwmbYdhFw21Fwbo+C35HMe36fTE0FBSR4KSfWg= -cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs= -cloud.google.com/go/gsuiteaddons v1.7.2 h1:Rma+a2tCB2PV0Rm87Ywr4P96dCwGIm8vw8gF23ZlYoY= -cloud.google.com/go/gsuiteaddons v1.7.2/go.mod h1:GD32J2rN/4APilqZw4JKmwV84+jowYYMkEVwQEYuAWc= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= -cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= -cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= -cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1 h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/iap v1.9.0 h1:RNhVq/6OMI99/wjPVhqFxjlBxYOBRdaG6rLpBvyaqYY= -cloud.google.com/go/iap v1.9.0/go.mod h1:01OFxd1R+NFrg78S+hoPV5PxEzv22HXaNqUUlmNHFuY= -cloud.google.com/go/iap v1.9.3 h1:M4vDbQ4TLXdaljXVZSwW7XtxpwXUUarY2lIs66m0aCM= -cloud.google.com/go/iap v1.9.4 h1:94zirc2r4t6KzhAMW0R6Dme005eTP6yf7g6vN4IhRrA= -cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w= -cloud.google.com/go/iap v1.10.2 h1:rvM+FNIF2wIbwUU8299FhhVGak2f7oOvbW8J/I5oflE= -cloud.google.com/go/iap v1.10.2/go.mod h1:cClgtI09VIfazEK6VMJr6bX8KQfuQ/D3xqX+d0wrUlI= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0 h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/ids v1.4.1 h1:khXYmSoDDhWGEVxHl4c4IgbwSRR+qE/L4hzP3vaU9Hc= -cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= -cloud.google.com/go/ids v1.4.4 h1:VuFqv2ctf/A7AyKlNxVvlHTzjrEvumWaZflUzBPz/M4= -cloud.google.com/go/ids v1.4.5 h1:xd4U7pgl3GHV+MABnv1BF4/Vy/zBF7CYC8XngkOLzag= -cloud.google.com/go/ids v1.4.5/go.mod h1:p0ZnyzjMWxww6d2DvMGnFwCsSxDJM666Iir1bK1UuBo= -cloud.google.com/go/ids v1.5.2 h1:EDYZQraE+Eq6BewUQxVRY8b3VUUo/MnjMfzSh1NGjx8= -cloud.google.com/go/ids v1.5.2/go.mod h1:P+ccDD96joXlomfonEdCnyrHvE68uLonc7sJBPVM5T0= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0 h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/iot v1.7.1 h1:yrH0OSmicD5bqGBoMlWG8UltzdLkYzNUwNVUVz7OT54= -cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= -cloud.google.com/go/iot v1.7.4 h1:m1WljtkZnvLTIRYW1YTOv5A6H1yKgLHR6nU7O8yf27w= -cloud.google.com/go/iot v1.7.5 h1:munTeBlbqI33iuTYgXy7S8lW2TCgi5l1hA4roSIY+EE= -cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0YsSsqs= -cloud.google.com/go/iot v1.8.2 h1:KMN0wujrPV7q0yfs4rt5CUl9Di8sQhJ0uohJn1h6yaI= -cloud.google.com/go/iot v1.8.2/go.mod h1:UDwVXvRD44JIcMZr8pzpF3o4iPsmOO6fmbaIYCAg1ww= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1 h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/kms v1.15.2 h1:lh6qra6oC4AyWe5fUUUBe/S27k12OHAleOOOw6KakdE= -cloud.google.com/go/kms v1.15.2/go.mod h1:3hopT4+7ooWRCjc2DxgnpESFxhIraaI2IpAVUEhbT/w= -cloud.google.com/go/kms v1.15.5 h1:pj1sRfut2eRbD9pFRjNnPNg/CzJPuQAzUujMIM1vVeM= -cloud.google.com/go/kms v1.15.6/go.mod h1:yF75jttnIdHfGBoE51AKsD/Yqf+/jICzB9v1s1acsms= -cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM= -cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= -cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= -cloud.google.com/go/kms v1.20.1/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzDqn2nc= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0 h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/language v1.11.0 h1:KnYolG0T5Oex722ZW/sP5QErhVAVNcqpJ16tVJd9RTw= -cloud.google.com/go/language v1.11.0/go.mod h1:uDx+pFDdAKTY8ehpWbiXyQdz8tDSYLJbQcXsCkjYyvQ= -cloud.google.com/go/language v1.12.2 h1:zg9uq2yS9PGIOdc0Kz/l+zMtOlxKWonZjjo5w5YPG2A= -cloud.google.com/go/language v1.12.3 h1:iaJZg6K4j/2PvZZVcjeO/btcWWIllVRBhuTFjGO4LXs= -cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8= -cloud.google.com/go/language v1.14.2 h1:rwrIOwcAgPTYbigOaiMSjKCvBy0xHZJbRc7HB/xMECA= -cloud.google.com/go/language v1.14.2/go.mod h1:dviAbkxT9art+2ioL9AM05t+3Ql6UPfMpwq1cDsF+rg= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0 h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/lifesciences v0.9.1 h1:axkANGx1wiBXHiPcJZAE+TDjjYoJRIDzbHC/WYllCBU= -cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= -cloud.google.com/go/lifesciences v0.9.4 h1:rZEI/UxcxVKEzyoRS/kdJ1VoolNItRWjNN0Uk9tfexg= -cloud.google.com/go/lifesciences v0.9.5 h1:gXvN70m2p+4zgJFzaz6gMKaxTuF9WJ0USYoMLWAOm8g= -cloud.google.com/go/lifesciences v0.9.5/go.mod h1:OdBm0n7C0Osh5yZB7j9BXyrMnTRGBJIZonUMxo5CzPw= -cloud.google.com/go/lifesciences v0.10.2 h1:eZSaRgBwbnb/oXwCj1SGE0Kp534DuXpg55iYBWgN024= -cloud.google.com/go/lifesciences v0.10.2/go.mod h1:vXDa34nz0T/ibUNoeHnhqI+Pn0OazUTdxemd0OLkyoY= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/logging v1.8.1 h1:26skQWPeYhvIasWKm48+Eq7oUqdcdbwsCVwz5Ys0FvU= -cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= -cloud.google.com/go/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw= -cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= -cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= -cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= -cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= -cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= -cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= -cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= -cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= -cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0 h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/managedidentities v1.6.1 h1:2/qZuOeLgUHorSdxSQGtnOu9xQkBn37+j+oZQv/KHJY= -cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= -cloud.google.com/go/managedidentities v1.6.4 h1:SF/u1IJduMqQQdJA4MDyivlIQ4SrV5qAawkr/ZEREkY= -cloud.google.com/go/managedidentities v1.6.5 h1:+bpih1piZVLxla/XBqeSUzJBp8gv9plGHIMAI7DLpDM= -cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI= -cloud.google.com/go/managedidentities v1.7.2 h1:oWxuIhIwQC1Vfs1SZi1x389W2TV9uyPsAyZMJgZDND4= -cloud.google.com/go/managedidentities v1.7.2/go.mod h1:t0WKYzagOoD3FNtJWSWcU8zpWZz2i9cw2sKa9RiPx5I= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0 h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/maps v1.4.0 h1:PdfgpBLhAoSzZrQXP+/zBc78fIPLZSJp5y8+qSMn2UU= -cloud.google.com/go/maps v1.4.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/maps v1.6.1 h1:2+eMp/1MvMPp5qrSOd3vtnLKa/pylt+krVRqET3jWsM= -cloud.google.com/go/maps v1.6.4 h1:EVCZAiDvog9So46460BGbCasPhi613exoaQbpilMVlk= -cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI= -cloud.google.com/go/maps v1.15.0 h1:bmFHlO6BL/smC6GD45r5j0ChjsyyevuJCSARdOL62TI= -cloud.google.com/go/maps v1.15.0/go.mod h1:ZFqZS04ucwFiHSNU8TBYDUr3wYhj5iBFJk24Ibvpf3o= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0 h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/mediatranslation v0.8.1 h1:50cF7c1l3BanfKrpnTCaTvhf+Fo6kdF21DG0byG7gYU= -cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= -cloud.google.com/go/mediatranslation v0.8.4 h1:VRCQfZB4s6jN0CSy7+cO3m4ewNwgVnaePanVCQh/9Z4= -cloud.google.com/go/mediatranslation v0.8.5 h1:c76KdIXljQHSCb/Cy47S8H4s05A4zbK3pAFGzwcczZo= -cloud.google.com/go/mediatranslation v0.8.5/go.mod h1:y7kTHYIPCIfgyLbKncgqouXJtLsU+26hZhHEEy80fSs= -cloud.google.com/go/mediatranslation v0.9.2 h1:p37R/k9+L33bUMO87gFyv93MwJ+9nuzVhXM5X+6ULwA= -cloud.google.com/go/mediatranslation v0.9.2/go.mod h1:1xyRoDYN32THzy+QaU62vIMciX0CFexplju9t30XwUc= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0 h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/memcache v1.10.1 h1:7lkLsF0QF+Mre0O/NvkD9Q5utUNwtzvIYjrOLOs0HO0= -cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= -cloud.google.com/go/memcache v1.10.4 h1:cdex/ayDd294XBj2cGeMe6Y+H1JvhN8y78B9UW7pxuQ= -cloud.google.com/go/memcache v1.10.5 h1:yeDv5qxRedFosvpMSEswrqUsJM5OdWvssPHFliNFTc4= -cloud.google.com/go/memcache v1.10.5/go.mod h1:/FcblbNd0FdMsx4natdj+2GWzTq+cjZvMa1I+9QsuMA= -cloud.google.com/go/memcache v1.11.2 h1:GGgC2A9AClJN8VLbMUAPUxj/dNMFwz6Lj01gDxPw7os= -cloud.google.com/go/memcache v1.11.2/go.mod h1:jIzHn79b0m5wbkax2SdlW5vNSbpaEk0yWHbeLpMIYZE= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0 h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/metastore v1.12.0 h1:+9DsxUOHvsqvC0ylrRc/JwzbXJaaBpfIK3tX0Lx8Tcc= -cloud.google.com/go/metastore v1.12.0/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/metastore v1.13.3 h1:94l/Yxg9oBZjin2bzI79oK05feYefieDq0o5fjLSkC8= -cloud.google.com/go/metastore v1.13.4 h1:dR7vqWXlK6IYR8Wbu9mdFfwlVjodIBhd1JRrpZftTEg= -cloud.google.com/go/metastore v1.13.4/go.mod h1:FMv9bvPInEfX9Ac1cVcRXp8EBBQnBcqH6gz3KvJ9BAE= -cloud.google.com/go/metastore v1.14.2 h1:Euc9kLTKS8T6M1JVqQavwDFHu9UtT1//lGXSKjpO3/0= -cloud.google.com/go/metastore v1.14.2/go.mod h1:dk4zOBhZIy3TFOQlI8sbOa+ef0FjAcCHEnd8dO2J+LE= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0 h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/monitoring v1.16.0 h1:rlndy4K8yknMY9JuGe2aK4SbCh21FXoCdX7SAGHmRgI= -cloud.google.com/go/monitoring v1.16.0/go.mod h1:Ptp15HgAyM1fNICAojDMoNc/wUmn67mLHQfyqbw+poY= -cloud.google.com/go/monitoring v1.16.3 h1:mf2SN9qSoBtIgiMA4R/y4VADPWZA7VCNJA079qLaZQ8= -cloud.google.com/go/monitoring v1.17.1/go.mod h1:SJzPMakCF0GHOuKEH/r4hxVKF04zl+cRPQyc3d/fqII= -cloud.google.com/go/monitoring v1.18.0 h1:NfkDLQDG2UR3WYZVQE8kwSbUIEyIqJUPl+aOQdFH1T4= -cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg= -cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= -cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0 h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkconnectivity v1.13.0 h1:kG2PX6URJ9Kvotfdm+hH8WIhrRY77sAKytUGOz+MgN0= -cloud.google.com/go/networkconnectivity v1.13.0/go.mod h1:SAnGPes88pl7QRLUen2HmcBSE9AowVAcdug8c0RSBFk= -cloud.google.com/go/networkconnectivity v1.14.3 h1:e9lUkCe2BexsqsUc2bjV8+gFBpQa54J+/F3qKVtW+wA= -cloud.google.com/go/networkconnectivity v1.14.4 h1:GBfXFhLyPspnaBE3nI/BRjdhW8vcbpT9QjE/4kDCDdc= -cloud.google.com/go/networkconnectivity v1.14.4/go.mod h1:PU12q++/IMnDJAB+3r+tJtuCXCfwfN+C6Niyj6ji1Po= -cloud.google.com/go/networkconnectivity v1.15.2 h1:CuBLrRKhPbzXkFGADopQUpMcdY+SSfoy/3RqsMH2pq4= -cloud.google.com/go/networkconnectivity v1.15.2/go.mod h1:N1O01bEk5z9bkkWwXLKcN2T53QN49m/pSpjfUvlHDQY= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0 h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networkmanagement v1.9.0 h1:aA6L8aioyM4S6nlPYzp2SvB88lBcByZmqMJM6ReafzU= -cloud.google.com/go/networkmanagement v1.9.0/go.mod h1:UTUaEU9YwbCAhhz3jEOHr+2/K/MrBk2XxOLS89LQzFw= -cloud.google.com/go/networkmanagement v1.9.3 h1:HsQk4FNKJUX04k3OI6gUsoveiHMGvDRqlaFM2xGyvqU= -cloud.google.com/go/networkmanagement v1.9.4 h1:aLV5GcosBNmd6M8+a0ekB0XlLRexv4fvnJJrYnqeBcg= -cloud.google.com/go/networkmanagement v1.9.4/go.mod h1:daWJAl0KTFytFL7ar33I6R/oNBH8eEOX/rBNHrC/8TA= -cloud.google.com/go/networkmanagement v1.16.0 h1:oT7c2Oo9NT54XjnP4GMNj/HEywrFnBz0u6QLJ2iu8NE= -cloud.google.com/go/networkmanagement v1.16.0/go.mod h1:Yc905R9U5jik5YMt76QWdG5WqzPU4ZsdI/mLnVa62/Q= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0 h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/networksecurity v0.9.1 h1:TBLEkMp3AE+6IV/wbIGRNTxnqLXHCTEQWoxRVC18TzY= -cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= -cloud.google.com/go/networksecurity v0.9.4 h1:947tNIPnj1bMGTIEBo3fc4QrrFKS5hh0bFVsHmFm4Vo= -cloud.google.com/go/networksecurity v0.9.5 h1:+caSxBTj0E8OYVh/5wElFdjEMO1S/rZtE1152Cepchc= -cloud.google.com/go/networksecurity v0.9.5/go.mod h1:KNkjH/RsylSGyyZ8wXpue8xpCEK+bTtvof8SBfIhMG8= -cloud.google.com/go/networksecurity v0.10.2 h1://zFZM8XZZs+3Y6QKuLqwD5tZ+B/17KUo/rJpGW2tJs= -cloud.google.com/go/networksecurity v0.10.2/go.mod h1:puU3Gwchd6Y/VTyMkL50GI2RSRMS3KXhcDBY1HSOcck= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0 h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/notebooks v1.10.0 h1:6x2K1JAWv6RW2yQO6oa+xtKUGOpGQseCmT94vpOt1vc= -cloud.google.com/go/notebooks v1.10.0/go.mod h1:SOPYMZnttHxqot0SGSFSkRrwE29eqnKPBJFqgWmiK2k= -cloud.google.com/go/notebooks v1.11.2 h1:eTOTfNL1yM6L/PCtquJwjWg7ZZGR0URFaFgbs8kllbM= -cloud.google.com/go/notebooks v1.11.3 h1:FH48boYmrWVQ6k0Mx/WrnNafXncT5iSYxA8CNyWTgy0= -cloud.google.com/go/notebooks v1.11.3/go.mod h1:0wQyI2dQC3AZyQqWnRsp+yA+kY4gC7ZIVP4Qg3AQcgo= -cloud.google.com/go/notebooks v1.12.2 h1:BHIH9kf/02wSCcLAVttEXHSFAgSotgRg2y1YjR7VDCc= -cloud.google.com/go/notebooks v1.12.2/go.mod h1:EkLwv8zwr8DUXnvzl944+sRBG+b73HEKzV632YYAGNI= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1 h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/optimization v1.5.0 h1:sGvPVtBJUKNYAwldhJvFmnM+EEdOXjDzjcly3g0n0Xg= -cloud.google.com/go/optimization v1.5.0/go.mod h1:evo1OvTxeBRBu6ydPlrIRizKY/LJKo/drDMMRKqGEUU= -cloud.google.com/go/optimization v1.6.2 h1:iFsoexcp13cGT3k/Hv8PA5aK+FP7FnbhwDO9llnruas= -cloud.google.com/go/optimization v1.6.3 h1:63NZaWyN+5rZEKHPX4ACpw3BjgyeuY8+rCehiCMaGPY= -cloud.google.com/go/optimization v1.6.3/go.mod h1:8ve3svp3W6NFcAEFr4SfJxrldzhUl4VMUJmhrqVKtYA= -cloud.google.com/go/optimization v1.7.2 h1:yM4teRB60qyIm8cV4VRW4wepmHbXCoqv3QKGfKzylEQ= -cloud.google.com/go/optimization v1.7.2/go.mod h1:msYgDIh1SGSfq6/KiWJQ/uxMkWq8LekPyn1LAZ7ifNE= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0 h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orchestration v1.8.1 h1:KmN18kE/xa1n91cM5jhCh7s1/UfIguSCisw7nTMUzgE= -cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= -cloud.google.com/go/orchestration v1.8.4 h1:kgwZ2f6qMMYIVBtUGGoU8yjYWwMTHDanLwM/CQCFaoQ= -cloud.google.com/go/orchestration v1.8.5 h1:YHgWMlrPttIVGItgGfuvO2KM7x+y9ivN/Yk92pMm1a4= -cloud.google.com/go/orchestration v1.8.5/go.mod h1:C1J7HesE96Ba8/hZ71ISTV2UAat0bwN+pi85ky38Yq8= -cloud.google.com/go/orchestration v1.11.1 h1:uZOwdQoAamx8+X0UdMqY/lro3/h/Zhb7SnfArufNVcc= -cloud.google.com/go/orchestration v1.11.1/go.mod h1:RFHf4g88Lbx6oKhwFstYiId2avwb6oswGeAQ7Tjjtfw= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0 h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/orgpolicy v1.11.1 h1:I/7dHICQkNwym9erHqmlb50LRU588NPCvkfIY0Bx9jI= -cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= -cloud.google.com/go/orgpolicy v1.11.4 h1:RWuXQDr9GDYhjmrredQJC7aY7cbyqP9ZuLbq5GJGves= -cloud.google.com/go/orgpolicy v1.12.1 h1:2JbXigqBJVp8Dx5dONUttFqewu4fP0p3pgOdIZAhpYU= -cloud.google.com/go/orgpolicy v1.12.1/go.mod h1:aibX78RDl5pcK3jA8ysDQCFkVxLj3aOQqrbBaUL2V5I= -cloud.google.com/go/orgpolicy v1.14.1 h1:c1QLoM5v8/aDKgYVCUaC039lD3GPvqAhTVOwsGhIoZQ= -cloud.google.com/go/orgpolicy v1.14.1/go.mod h1:1z08Hsu1mkoH839X7C8JmnrqOkp2IZRSxiDw7W/Xpg4= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0 h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/osconfig v1.12.1 h1:dgyEHdfqML6cUW6/MkihNdTVc0INQst0qSE8Ou1ub9c= -cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= -cloud.google.com/go/osconfig v1.12.4 h1:OrRCIYEAbrbXdhm13/JINn9pQchvTTIzgmOCA7uJw8I= -cloud.google.com/go/osconfig v1.12.5 h1:Mo5jGAxOMKH/PmDY7fgY19yFcVbvwREb5D5zMPQjFfo= -cloud.google.com/go/osconfig v1.12.5/go.mod h1:D9QFdxzfjgw3h/+ZaAb5NypM8bhOMqBzgmbhzWViiW8= -cloud.google.com/go/osconfig v1.14.2 h1:iBN87PQc+EGh5QqijM3CuxcibvDWmF+9k0eOJT27FO4= -cloud.google.com/go/osconfig v1.14.2/go.mod h1:kHtsm0/j8ubyuzGciBsRxFlbWVjc4c7KdrwJw0+g+pQ= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0 h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/oslogin v1.10.1 h1:LdSuG3xBYu2Sgr3jTUULL1XCl5QBx6xwzGqzoDUw1j0= -cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= -cloud.google.com/go/oslogin v1.12.2 h1:NP/KgsD9+0r9hmHC5wKye0vJXVwdciv219DtYKYjgqE= -cloud.google.com/go/oslogin v1.13.1 h1:1K4nOT5VEZNt7XkhaTXupBYos5HjzvJMfhvyD2wWdFs= -cloud.google.com/go/oslogin v1.13.1/go.mod h1:vS8Sr/jR7QvPWpCjNqy6LYZr5Zs1e8ZGW/KPn9gmhws= -cloud.google.com/go/oslogin v1.14.2 h1:6ehIKkALrLe9zUHwEmfXRVuSPm3HiUmEnnDRr7yLIo8= -cloud.google.com/go/oslogin v1.14.2/go.mod h1:M7tAefCr6e9LFTrdWRQRrmMeKHbkvc4D9g6tHIjHySA= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0 h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/phishingprotection v0.8.1 h1:aK/lNmSd1vtbft/vLe2g7edXK72sIQbqr2QyrZN/iME= -cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= -cloud.google.com/go/phishingprotection v0.8.4 h1:sPLUQkHq6b4AL0czSJZ0jd6vL55GSTHz2B3Md+TCZI0= -cloud.google.com/go/phishingprotection v0.8.5 h1:DH3WFLzEoJdW/6xgsmoDqOwT1xddFi7gKu0QGZQhpGU= -cloud.google.com/go/phishingprotection v0.8.5/go.mod h1:g1smd68F7mF1hgQPuYn3z8HDbNre8L6Z0b7XMYFmX7I= -cloud.google.com/go/phishingprotection v0.9.2 h1:SaW0IPf/1fflnzomjy7+9EMtReXuxkYpUAf/77m5xL8= -cloud.google.com/go/phishingprotection v0.9.2/go.mod h1:mSCiq3tD8fTJAuXq5QBHFKZqMUy8SfWsbUM9NpzJIRQ= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0 h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/policytroubleshooter v1.9.0 h1:pT4qSiL5o0hBSWHDiOcmes/s301PeLLWEhAr/eMQB/g= -cloud.google.com/go/policytroubleshooter v1.9.0/go.mod h1:+E2Lga7TycpeSTj2FsH4oXxTnrbHJGRlKhVZBLGgU64= -cloud.google.com/go/policytroubleshooter v1.10.2 h1:sq+ScLP83d7GJy9+wpwYJVnY+q6xNTXwOdRIuYjvHT4= -cloud.google.com/go/policytroubleshooter v1.10.3 h1:c0WOzC6hz964QWNBkyKfna8A2jOIx1zzZa43Gx/P09o= -cloud.google.com/go/policytroubleshooter v1.10.3/go.mod h1:+ZqG3agHT7WPb4EBIRqUv4OyIwRTZvsVDHZ8GlZaoxk= -cloud.google.com/go/policytroubleshooter v1.11.2 h1:sTIH5AQ8tcgmnqrqlZfYWymjMhPh4ZEt4CvQGgG+kzc= -cloud.google.com/go/policytroubleshooter v1.11.2/go.mod h1:1TdeCRv8Qsjcz2qC3wFltg/Mjga4HSpv8Tyr5rzvPsw= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0 h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/privatecatalog v0.9.1 h1:B/18xGo+E0EMS9LOEQ0zXz7F2asMgmVgTYGSI89MHOA= -cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= -cloud.google.com/go/privatecatalog v0.9.4 h1:Vo10IpWKbNvc/z/QZPVXgCiwfjpWoZ/wbgful4Uh/4E= -cloud.google.com/go/privatecatalog v0.9.5 h1:UZ0assTnATXSggoxUIh61RjTQ4P9zCMk/kEMbn0nMYA= -cloud.google.com/go/privatecatalog v0.9.5/go.mod h1:fVWeBOVe7uj2n3kWRGlUQqR/pOd450J9yZoOECcQqJk= -cloud.google.com/go/privatecatalog v0.10.2 h1:01RPfn8IL2//8UHAmImRraTFYM/3gAEiIxudWLWrp+0= -cloud.google.com/go/privatecatalog v0.10.2/go.mod h1:o124dHoxdbO50ImR3T4+x3GRwBSTf4XTn6AatP8MgsQ= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= -cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0 h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsub v1.33.0 h1:6SPCPvWav64tj0sVX/+npCBKhUi/UjJehy9op/V3p2g= -cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsub v1.36.1 h1:dfEPuGCHGbWUhaMCTHUFjfroILEkx55iUmKBZTP5f+Y= -cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= -cloud.google.com/go/pubsub v1.45.1 h1:ZC/UzYcrmK12THWn1P72z+Pnp2vu/zCZRXyhAfP1hJY= -cloud.google.com/go/pubsub v1.45.1/go.mod h1:3bn7fTmzZFwaUjllitv1WlsNMkqBgGUb3UdMhI54eCc= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0 h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/pubsublite v1.8.1 h1:pX+idpWMIH30/K7c0epN6V703xpIcMXWRjKJsz0tYGY= -cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= -cloud.google.com/go/pubsublite v1.8.2 h1:jLQozsEVr+c6tOU13vDugtnaBSUy/PD5zK6mhm+uF1Y= -cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= -cloud.google.com/go/recaptchaenterprise v1.3.1 h1:u6EznTGzIdsyOsvm+Xkw0aSuKFXQlyjGE9a4exk6iNQ= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0 h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2 h1:IGkbudobsTXAwmkEYOzPCQPApUCsN4Gbq3ndGVhHQpI= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= -cloud.google.com/go/recaptchaenterprise/v2 v2.8.3 h1:UaV9C58snc5IsRQ6NN65jmRGnTdPT7mYZzK4Vbun+ik= -cloud.google.com/go/recaptchaenterprise/v2 v2.8.3/go.mod h1:Dak54rw6lC2gBY8FBznpOCAR58wKf+R+ZSJRoeJok4w= -cloud.google.com/go/recaptchaenterprise/v2 v2.8.4 h1:KOlLHLv3h3HwcZAkx91ubM3Oztz3JtT3ZacAJhWDorQ= -cloud.google.com/go/recaptchaenterprise/v2 v2.9.2 h1:U3Wfq12X9cVMuTpsWDSURnXF0Z9hSPTHj+xsnXDRLsw= -cloud.google.com/go/recaptchaenterprise/v2 v2.9.2/go.mod h1:trwwGkfhCmp05Ll5MSJPXY7yvnO0p4v3orGANAFHAuU= -cloud.google.com/go/recaptchaenterprise/v2 v2.19.0 h1:J/J7ZeVOX+sqn0hxzkOBfnQfBAzPZt8KaAuQoarQWQM= -cloud.google.com/go/recaptchaenterprise/v2 v2.19.0/go.mod h1:vnbA2SpVPPwKeoFrCQxR+5a0JFRRytwBBG69Zj9pGfk= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0 h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommendationengine v0.8.1 h1:nMr1OEVHuDambRn+/y4RmNAmnR/pXCuHtH0Y4tCgGRQ= -cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= -cloud.google.com/go/recommendationengine v0.8.4 h1:JRiwe4hvu3auuh2hujiTc2qNgPPfVp+Q8KOpsXlEzKQ= -cloud.google.com/go/recommendationengine v0.8.5 h1:ineqLswaCSBY0csYv5/wuXJMBlxATK6Xc5jJkpiTEdM= -cloud.google.com/go/recommendationengine v0.8.5/go.mod h1:A38rIXHGFvoPvmy6pZLozr0g59NRNREz4cx7F58HAsQ= -cloud.google.com/go/recommendationengine v0.9.2 h1:RHVdmoNBdzgRJXI/3SV+GB5TTv/umsVguiaEvmKOh98= -cloud.google.com/go/recommendationengine v0.9.2/go.mod h1:DjGfWZJ68ZF5ZuNgoTVXgajFAG0yLt4CJOpC0aMK3yw= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0 h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/recommender v1.11.0 h1:SuzbMJhDAiPro7tR9QP7EX97+TI31urjsIgNh9XQHl8= -cloud.google.com/go/recommender v1.11.0/go.mod h1:kPiRQhPyTJ9kyXPCG6u/dlPLbYfFlkwHNRwdzPVAoII= -cloud.google.com/go/recommender v1.11.3 h1:VndmgyS/J3+izR8V8BHa7HV/uun8//ivQ3k5eVKKyyM= -cloud.google.com/go/recommender v1.12.1 h1:LVLYS3r3u0MSCxQSDUtLSkporEGi9OAE6hGvayrZNPs= -cloud.google.com/go/recommender v1.12.1/go.mod h1:gf95SInWNND5aPas3yjwl0I572dtudMhMIG4ni8nr+0= -cloud.google.com/go/recommender v1.13.2 h1:xDFzlFk5Xp5MXnac468eicKM3MUo6UNdxoYuBMOF1mE= -cloud.google.com/go/recommender v1.13.2/go.mod h1:XJau4M5Re8F4BM+fzF3fqSjxNJuM66fwF68VCy/ngGE= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0 h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/redis v1.13.1 h1:YrjQnCC7ydk+k30op7DSjSHw1yAYhqYXFcOq1bSXRYA= -cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= -cloud.google.com/go/redis v1.14.1 h1:J9cEHxG9YLmA9o4jTSvWt/RuVEn6MTrPlYSCRHujxDQ= -cloud.google.com/go/redis v1.14.2 h1:QF0maEdVv0Fj/2roU8sX3NpiDBzP9ICYTO+5F32gQNo= -cloud.google.com/go/redis v1.14.2/go.mod h1:g0Lu7RRRz46ENdFKQ2EcQZBAJ2PtJHJLuiiRuEXwyQw= -cloud.google.com/go/redis v1.17.2 h1:QbW264RBH+NSVEQqlDoHfoxcreXK8QRRByTOR2CFbJs= -cloud.google.com/go/redis v1.17.2/go.mod h1:h071xkcTMnJgQnU/zRMOVKNj5J6AttG16RDo+VndoNo= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0 h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcemanager v1.9.1 h1:QIAMfndPOHR6yTmMUB0ZN+HSeRmPjR/21Smq5/xwghI= -cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= -cloud.google.com/go/resourcemanager v1.9.4 h1:JwZ7Ggle54XQ/FVYSBrMLOQIKoIT/uer8mmNvNLK51k= -cloud.google.com/go/resourcemanager v1.9.5 h1:AZWr1vWVDKGwfLsVhcN+vcwOz3xqqYxtmMa0aABCMms= -cloud.google.com/go/resourcemanager v1.9.5/go.mod h1:hep6KjelHA+ToEjOfO3garMKi/CLYwTqeAw7YiEI9x8= -cloud.google.com/go/resourcemanager v1.10.2 h1:LpqZZGM0uJiu1YWM878AA8zZ/qOQ/Ngno60Q8RAraAI= -cloud.google.com/go/resourcemanager v1.10.2/go.mod h1:5f+4zTM/ZOTDm6MmPOp6BQAhR0fi8qFPnvVGSoWszcc= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0 h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/resourcesettings v1.6.1 h1:Fdyq418U69LhvNPFdlEO29w+DRRjwDA4/pFamm4ksAg= -cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= -cloud.google.com/go/resourcesettings v1.6.4 h1:yTIL2CsZswmMfFyx2Ic77oLVzfBFoWBYgpkgiSPnC4Y= -cloud.google.com/go/resourcesettings v1.6.5 h1:BTr5MVykJwClASci/7Og4Qfx70aQ4n3epsNLj94ZYgw= -cloud.google.com/go/resourcesettings v1.6.5/go.mod h1:WBOIWZraXZOGAgoR4ukNj0o0HiSMO62H9RpFi9WjP9I= -cloud.google.com/go/resourcesettings v1.8.2 h1:ISRX2HZHNS17F/EuIwzPrQwEyIyUJayGuLrS51yt6Wk= -cloud.google.com/go/resourcesettings v1.8.2/go.mod h1:uEgtPiMA+xuBUM4Exu+ZkNpMYP0BLlYeJbyNHfrc+U0= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0 h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/retail v1.14.1 h1:gYBrb9u/Hc5s5lUTFXX1Vsbc/9BEvgtioY6ZKaK0DK8= -cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= -cloud.google.com/go/retail v1.14.4 h1:geqdX1FNqqL2p0ADXjPpw8lq986iv5GrVcieTYafuJQ= -cloud.google.com/go/retail v1.15.1/go.mod h1:In9nSBOYhLbDGa87QvWlnE1XA14xBN2FpQRiRsUs9wU= -cloud.google.com/go/retail v1.16.0 h1:Fn1GuAua1c6crCGqfJ1qMxG1Xh10Tg/x5EUODEHMqkw= -cloud.google.com/go/retail v1.16.0/go.mod h1:LW7tllVveZo4ReWt68VnldZFWJRzsh9np+01J9dYWzE= -cloud.google.com/go/retail v1.19.1 h1:FVzvA+VuEdNoMz2WzWZ5KwfG+CX+jSv+SOspyQPLuRs= -cloud.google.com/go/retail v1.19.1/go.mod h1:W48zg0zmt2JMqmJKCuzx0/0XDLtovwzGAeJjmv6VPaE= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0 h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/run v1.2.0 h1:kHeIG8q+N6Zv0nDkBjSOYfK2eWqa5FnaiDPH/7/HirE= -cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= -cloud.google.com/go/run v1.3.3 h1:qdfZteAm+vgzN1iXzILo3nJFQbzziudkJrvd9wCf3FQ= -cloud.google.com/go/run v1.3.4 h1:m9WDA7DzTpczhZggwYlZcBWgCRb+kgSIisWn1sbw2rQ= -cloud.google.com/go/run v1.3.4/go.mod h1:FGieuZvQ3tj1e9GnzXqrMABSuir38AJg5xhiYq+SF3o= -cloud.google.com/go/run v1.7.0 h1:GJtHWUgi8CK+YPhmTR3tKBAmDmU9RRMYqiGKCmIgFG8= -cloud.google.com/go/run v1.7.0/go.mod h1:IvJOg2TBb/5a0Qkc6crn5yTy5nkjcgSWQLhgO8QL8PQ= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0 h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/scheduler v1.10.1 h1:yoZbZR8880KgPGLmACOMCiY2tPk+iX4V/dkxqTirlz8= -cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= -cloud.google.com/go/scheduler v1.10.4 h1:LXm6L6IYW3Fy8lxU7kvT7r6JiW/noxn2gItJmsvwzV4= -cloud.google.com/go/scheduler v1.10.4/go.mod h1:MTuXcrJC9tqOHhixdbHDFSIuh7xZF2IysiINDuiq6NI= -cloud.google.com/go/scheduler v1.10.5 h1:eMEettHlFhG5pXsoHouIM5nRT+k+zU4+GUvRtnxhuVI= -cloud.google.com/go/scheduler v1.10.6 h1:5U8iXLoQ03qOB+ZXlAecU7fiE33+u3QiM9nh4cd0eTE= -cloud.google.com/go/scheduler v1.10.6/go.mod h1:pe2pNCtJ+R01E06XCDOJs1XvAMbv28ZsQEbqknxGOuE= -cloud.google.com/go/scheduler v1.11.2 h1:PfkvJP1qKu9NvFB65Ja/s918bPZWMBcYkg35Ljdw1Oc= -cloud.google.com/go/scheduler v1.11.2/go.mod h1:GZSv76T+KTssX2I9WukIYQuQRf7jk1WI+LOcIEHUUHk= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/secretmanager v1.11.1 h1:cLTCwAjFh9fKvU6F13Y4L9vPcx9yiWPyWXE4+zkuEQs= -cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= -cloud.google.com/go/secretmanager v1.11.4 h1:krnX9qpG2kR2fJ+u+uNyNo+ACVhplIAS4Pu7u+4gd+k= -cloud.google.com/go/secretmanager v1.11.5 h1:82fpF5vBBvu9XW4qj0FU2C6qVMtj1RM/XHwKXUEAfYY= -cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0RdrMeZIASKc+S7VqH4= -cloud.google.com/go/secretmanager v1.14.2 h1:2XscWCfy//l/qF96YE18/oUaNJynAx749Jg3u0CjQr8= -cloud.google.com/go/secretmanager v1.14.2/go.mod h1:Q18wAPMM6RXLC/zVpWTlqq2IBSbbm7pKBlM3lCKsmjw= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0 h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/security v1.15.1 h1:jR3itwycg/TgGA0uIgTItcVhA55hKWiNJxaNNpQJaZE= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/security v1.15.4 h1:sdnh4Islb1ljaNhpIXlIPgb3eYj70QWgPVDKOUYvzJc= -cloud.google.com/go/security v1.15.5 h1:wTKJQ10j8EYgvE8Y+KhovxDRVDk2iv/OsxZ6GrLP3kE= -cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc= -cloud.google.com/go/security v1.18.2 h1:9Nzp9LGjiDvHqy7X7Q9GrS5lIHN0bI8RvDjkrl4ILO0= -cloud.google.com/go/security v1.18.2/go.mod h1:3EwTcYw8554iEtgK8VxAjZaq2unFehcsgFIF9nOvQmU= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0 h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/securitycenter v1.23.0 h1:XOGJ9OpnDtqg8izd7gYk/XUhj8ytjIalyjjsR6oyG0M= -cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= -cloud.google.com/go/securitycenter v1.24.2 h1:qCEyXoJoxNKKA1bDywBjjqCB7ODXazzHnVWnG5Uqd1M= -cloud.google.com/go/securitycenter v1.24.4 h1:/5jjkZ+uGe8hZ7pvd7pO30VW/a+pT2MrrdgOqjyucKQ= -cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU= -cloud.google.com/go/securitycenter v1.35.2 h1:XkkE+IRE5/88drGPIuvETCSN7dAnWoqJahZzDbP5Hog= -cloud.google.com/go/securitycenter v1.35.2/go.mod h1:AVM2V9CJvaWGZRHf3eG+LeSTSissbufD27AVBI91C8s= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1 h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0 h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicedirectory v1.11.0 h1:pBWpjCFVGWkzVTkqN3TBBIqNSoSHY86/6RL0soSQ4z8= -cloud.google.com/go/servicedirectory v1.11.0/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicedirectory v1.11.3 h1:5niCMfkw+jifmFtbBrtRedbXkJm3fubSR/KHbxSJZVM= -cloud.google.com/go/servicedirectory v1.11.4 h1:da7HFI1229kyzIyuVEzHXip0cw0d+E0s8mjQby0WN+k= -cloud.google.com/go/servicedirectory v1.11.4/go.mod h1:Bz2T9t+/Ehg6x+Y7Ycq5xiShYLD96NfEsWNHyitj1qM= -cloud.google.com/go/servicedirectory v1.12.2 h1:W/oZmTUzlWbeSTujRbmG9v7HZyHcorj608tkcD3vVYE= -cloud.google.com/go/servicedirectory v1.12.2/go.mod h1:F0TJdFjqqotiZRlMXgIOzszaplk4ZAmUV8ovHo08M2U= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0 h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/shell v1.7.1 h1:aHbwH9LSqs4r2rbay9f6fKEls61TAjT63jSyglsw7sI= -cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= -cloud.google.com/go/shell v1.7.4 h1:nurhlJcSVFZneoRZgkBEHumTYf/kFJptCK2eBUq/88M= -cloud.google.com/go/shell v1.7.5 h1:3Fq2hzO0ZSyaqBboJrFkwwf/qMufDtqwwA6ep8EZxEI= -cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE= -cloud.google.com/go/shell v1.8.2 h1:lSfdEng3n7zZHzC40BJ4trEMyme3CGnLLnA09MlLQdQ= -cloud.google.com/go/shell v1.8.2/go.mod h1:QQR12T6j/eKvqAQLv6R3ozeoqwJ0euaFSz2qLqG93Bs= -cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0 h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.49.0 h1:+HY8C4uztU7XyLz3xMi/LCXdetLEOExhvRFJu2NiVXM= -cloud.google.com/go/spanner v1.49.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= -cloud.google.com/go/spanner v1.51.0 h1:l3exhhsVMKsx1E7Xd1QajYSvHmI1KZoWPW5tRxIIdvQ= -cloud.google.com/go/spanner v1.51.0/go.mod h1:c5KNo5LQ1X5tJwma9rSQZsXNBDNvj4/n8BVc3LNahq0= -cloud.google.com/go/spanner v1.53.0 h1:/NzWQJ1MEhdRcffiutRKbW/AIGVKhcTeivWTDjEyCCo= -cloud.google.com/go/spanner v1.56.0 h1:o/Cv7/zZ1WgRXVCd5g3Nc23ZI39p/1pWFqFwvg6Wcu8= -cloud.google.com/go/spanner v1.56.0/go.mod h1:DndqtUKQAt3VLuV2Le+9Y3WTnq5cNKrnLb/Piqcj+h0= -cloud.google.com/go/spanner v1.73.0 h1:0bab8QDn6MNj9lNK6XyGAVFhMlhMU2waePPa6GZNoi8= -cloud.google.com/go/spanner v1.73.0/go.mod h1:mw98ua5ggQXVWwp83yjwggqEmW9t8rjs9Po1ohcUGW4= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0 h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/speech v1.19.0 h1:MCagaq8ObV2tr1kZJcJYgXYbIn8Ai5rp42tyGYw9rls= -cloud.google.com/go/speech v1.19.0/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/speech v1.20.1 h1:OpJ666ao7XxXewGSAkDUJnW188tJ5hNPoM7pZB+Q730= -cloud.google.com/go/speech v1.20.1/go.mod h1:wwolycgONvfz2EDU8rKuHRW3+wc9ILPsAWoikBEWavY= -cloud.google.com/go/speech v1.21.0 h1:qkxNao58oF8ghAHE1Eghen7XepawYEN5zuZXYWaUTA4= -cloud.google.com/go/speech v1.21.1 h1:nuFc+Kj5B8de75nN4FdPyUbI2SiBoHZG6BLurXL56Q0= -cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA= -cloud.google.com/go/speech v1.25.2 h1:rKOXU9LAZTOYHhRNB4gZDekNjJx21TktQpetBa5IzOk= -cloud.google.com/go/speech v1.25.2/go.mod h1:KPFirZlLL8SqPaTtG6l+HHIFHPipjbemv4iFg7rTlYs= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY= -cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storage v1.33.0 h1:PVrDOkIC8qQVa1P3SXGpQvfuJhN2LHOoyZvWs8D2X5M= -cloud.google.com/go/storage v1.33.0/go.mod h1:Hhh/dogNRGca7IWv1RC2YqEn0c0G77ctA/OxflYkiD8= -cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= -cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= -cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= -cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= -cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0 h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/storagetransfer v1.10.0 h1:+ZLkeXx0K0Pk5XdDmG0MnUVqIR18lllsihU/yq39I8Q= -cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= -cloud.google.com/go/storagetransfer v1.10.3 h1:YM1dnj5gLjfL6aDldO2s4GeU8JoAvH1xyIwXre63KmI= -cloud.google.com/go/storagetransfer v1.10.4 h1:dy4fL3wO0VABvzM05ycMUPFHxTPbJz9Em8ikAJVqSbI= -cloud.google.com/go/storagetransfer v1.10.4/go.mod h1:vef30rZKu5HSEf/x1tK3WfWrL0XVoUQN/EPDRGPzjZs= -cloud.google.com/go/storagetransfer v1.11.2 h1:hMcP8ECmxedXjPxr2j3Ca45ro/TKEF+1YYjq2p5LMTI= -cloud.google.com/go/storagetransfer v1.11.2/go.mod h1:FcM29aY4EyZ3yVPmW5SxhqUdhjgPBUOFyy4rqiQbias= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0 h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/talent v1.6.2 h1:j46ZgD6N2YdpFPux9mc7OAf4YK3tiBCsbLKc8rQx+bU= -cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= -cloud.google.com/go/talent v1.6.5 h1:LnRJhhYkODDBoTwf6BeYkiJHFw9k+1mAFNyArwZUZAs= -cloud.google.com/go/talent v1.6.6 h1:JssV0CE3FNujuSWn7SkosOzg7qrMxVnt6txOfGcMSa4= -cloud.google.com/go/talent v1.6.6/go.mod h1:y/WQDKrhVz12WagoarpAIyKKMeKGKHWPoReZ0g8tseQ= -cloud.google.com/go/talent v1.7.2 h1:KONR7KX/EXI3pO2cbSIDOBqhBzvgDS71vaMz8k4qRCg= -cloud.google.com/go/talent v1.7.2/go.mod h1:k1sqlDgS9gbc0gMTRuRQpX6C6VB7bGUxSPcoTRWJod8= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0 h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/texttospeech v1.7.1 h1:S/pR/GZT9p15R7Y2dk2OXD/3AufTct/NSxT4a7nxByw= -cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= -cloud.google.com/go/texttospeech v1.7.4 h1:ahrzTgr7uAbvebuhkBAAVU6kRwVD0HWsmDsvMhtad5Q= -cloud.google.com/go/texttospeech v1.7.5 h1:dxY2Q5mHCbrGa3oPR2O3PCicdnvKa1JmwGQK36EFLOw= -cloud.google.com/go/texttospeech v1.7.5/go.mod h1:tzpCuNWPwrNJnEa4Pu5taALuZL4QRRLcb+K9pbhXT6M= -cloud.google.com/go/texttospeech v1.10.0 h1:icRAxYDtq3zO1T0YBT/fe8C/7pXoIqfkY4iYr5zG39I= -cloud.google.com/go/texttospeech v1.10.0/go.mod h1:215FpCOyRxxrS7DSb2t7f4ylMz8dXsQg8+Vdup5IhP4= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0 h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/tpu v1.6.1 h1:kQf1jgPY04UJBYYjNUO+3GrZtIb57MfGAW2bwgLbR3A= -cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= -cloud.google.com/go/tpu v1.6.4 h1:XIEH5c0WeYGaVy9H+UueiTaf3NI6XNdB4/v6TFQJxtE= -cloud.google.com/go/tpu v1.6.5 h1:C8YyYda8WtNdBoCgFwwBzZd+S6+EScHOxM/z1h0NNp8= -cloud.google.com/go/tpu v1.6.5/go.mod h1:P9DFOEBIBhuEcZhXi+wPoVy/cji+0ICFi4TtTkMHSSs= -cloud.google.com/go/tpu v1.7.2 h1:xPBJd7xZgtl3CgrZoaUf7zFPVVj68jmzzGTSzkcsOtQ= -cloud.google.com/go/tpu v1.7.2/go.mod h1:0Y7dUo2LIbDUx0yQ/vnLC6e18FK6NrDfAhYS9wZ/2vs= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0 h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/trace v1.10.1 h1:EwGdOLCNfYOOPtgqo+D2sDLZmRCEO1AagRTJCU6ztdg= -cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= -cloud.google.com/go/trace v1.10.4 h1:2qOAuAzNezwW3QN+t41BtkDJOG42HywL73q8x/f6fnM= -cloud.google.com/go/trace v1.10.5 h1:0pr4lIKJ5XZFYD9GtxXEWr0KkVeigc3wlGpZco0X1oA= -cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= -cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= -cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0 h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.9.0 h1:0na4gC54Lu05ir00dmUSuMkLAojDe1ALq4hBTUkhwjE= -cloud.google.com/go/translate v1.9.0/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/translate v1.9.3 h1:t5WXTqlrk8VVJu/i3WrYQACjzYJiff5szARHiyqqPzI= -cloud.google.com/go/translate v1.10.1 h1:upovZ0wRMdzZvXnu+RPam41B0mRJ+coRXFP2cYFJ7ew= -cloud.google.com/go/translate v1.10.1/go.mod h1:adGZcQNom/3ogU65N9UXHOnnSvjPwA/jKQUMnsYXOyk= -cloud.google.com/go/translate v1.12.2 h1:qECivi8O+jFI/vnvN9elK6CME+WAWy56GIBszF+/rNc= -cloud.google.com/go/translate v1.12.2/go.mod h1:jjLVf2SVH2uD+BNM40DYvRRKSsuyKxVvs3YjTW/XSWY= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0 h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.20.0 h1:AkjXyJfQ7DtPyDOAbTMeiGcuKsO8/iKSb3fAmTUHYSg= -cloud.google.com/go/video v1.20.0/go.mod h1:U3G3FTnsvAGqglq9LxgqzOiBc/Nt8zis8S+850N2DUM= -cloud.google.com/go/video v1.20.3 h1:Xrpbm2S9UFQ1pZEeJt9Vqm5t2T/z9y/M3rNXhFoo8Is= -cloud.google.com/go/video v1.20.4 h1:TXwotxkShP1OqgKsbd+b8N5hrIHavSyLGvYnLGCZ7xc= -cloud.google.com/go/video v1.20.4/go.mod h1:LyUVjyW+Bwj7dh3UJnUGZfyqjEto9DnrvTe1f/+QrW0= -cloud.google.com/go/video v1.23.2 h1:CGAPOXTJMoZm9PeHkohBlMTy8lqN6VWCNDjp5VODfy8= -cloud.google.com/go/video v1.23.2/go.mod h1:rNOr2pPHWeCbW0QsOwJRIe0ZiuwHpHtumK0xbiYB1Ew= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0 h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/videointelligence v1.11.1 h1:MBMWnkQ78GQnRz5lfdTAbBq/8QMCF3wahgtHh3s/J+k= -cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= -cloud.google.com/go/videointelligence v1.11.4 h1:YS4j7lY0zxYyneTFXjBJUj2r4CFe/UoIi/PJG0Zt/Rg= -cloud.google.com/go/videointelligence v1.11.5 h1:mYaWH8uhUCXLJCN3gdXswKzRa2+lK0zN6/KsIubm6pE= -cloud.google.com/go/videointelligence v1.11.5/go.mod h1:/PkeQjpRponmOerPeJxNPuxvi12HlW7Em0lJO14FC3I= -cloud.google.com/go/videointelligence v1.12.2 h1:ZLElysepw9vfQGAKWfnxdnSnHSKbEn/nU/tmBnCJLfA= -cloud.google.com/go/videointelligence v1.12.2/go.mod h1:8xKGlq0lNVyT8JgTkkCUCpyNJnYYEJVWGdqzv+UcwR8= -cloud.google.com/go/vision v1.2.0 h1:/CsSTkbmO9HC8iQpxbK8ATms3OQaX3YQUeTMGCxlaK4= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0 h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vision/v2 v2.7.2 h1:ccK6/YgPfGHR/CyESz1mvIbsht5Y2xRsWCPqmTNydEw= -cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= -cloud.google.com/go/vision/v2 v2.7.5 h1:T/ujUghvEaTb+YnFY/jiYwVAkMbIC8EieK0CJo6B4vg= -cloud.google.com/go/vision/v2 v2.7.6/go.mod h1:ZkvWTVNPBU3YZYzgF9Y1jwEbD1NBOCyJn0KFdQfE6Bw= -cloud.google.com/go/vision/v2 v2.8.0 h1:W52z1b6LdGI66MVhE70g/NFty9zCYYcjdKuycqmlhtg= -cloud.google.com/go/vision/v2 v2.8.0/go.mod h1:ocqDiA2j97pvgogdyhoxiQp2ZkDCyr0HWpicywGGRhU= -cloud.google.com/go/vision/v2 v2.9.2 h1:u4pu3gKps88oUe76WwVPeX9dgWVyyYopZ1s05FwsKEk= -cloud.google.com/go/vision/v2 v2.9.2/go.mod h1:WuxjVQdAy4j4WZqY5Rr655EdAgi8B707Vdb5T8c90uo= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0 h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmmigration v1.7.1 h1:gnjIclgqbEMc+cF5IJuPxp53wjBIlqZ8h9hE8Rkwp7A= -cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= -cloud.google.com/go/vmmigration v1.7.4 h1:qPNdab4aGgtaRX+51jCOtJxlJp6P26qua4o1xxUDjpc= -cloud.google.com/go/vmmigration v1.7.5 h1:5v9RT2vWyuw3pK2ox0HQpkoftO7Q7/8591dTxxQc79g= -cloud.google.com/go/vmmigration v1.7.5/go.mod h1:pkvO6huVnVWzkFioxSghZxIGcsstDvYiVCxQ9ZH3eYI= -cloud.google.com/go/vmmigration v1.8.2 h1:Hpqv3fZ3Ri1OMhTNVJgxxsTou2ZlRzKbnc1dSybTP5Y= -cloud.google.com/go/vmmigration v1.8.2/go.mod h1:FBejrsr8ZHmJb949BSOyr3D+/yCp9z9Hk0WtsTiHc1Q= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0 h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vmwareengine v1.0.0 h1:qsJ0CPlOQu/3MFBGklu752v3AkD+Pdu091UmXJ+EjTA= -cloud.google.com/go/vmwareengine v1.0.0/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vmwareengine v1.0.3 h1:WY526PqM6QNmFHSqe2sRfK6gRpzWjmL98UFkql2+JDM= -cloud.google.com/go/vmwareengine v1.1.1 h1:EGdDi9QbqThfZq3ILcDK5g+m9jTevc34AY5tACx5v7k= -cloud.google.com/go/vmwareengine v1.1.1/go.mod h1:nMpdsIVkUrSaX8UvmnBhzVzG7PPvNYc5BszcvIVudYs= -cloud.google.com/go/vmwareengine v1.3.2 h1:LmkojgSLvsRwU1+c0iiY2XoBkXYKzpArElHC9IDWakg= -cloud.google.com/go/vmwareengine v1.3.2/go.mod h1:JsheEadzT0nfXOGkdnwtS1FhFAnj4g8qhi4rKeLi/AU= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0 h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/vpcaccess v1.7.1 h1:ram0GzjNWElmbxXMIzeOZUkQ9J8ZAahD6V8ilPGqX0Y= -cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= -cloud.google.com/go/vpcaccess v1.7.4 h1:zbs3V+9ux45KYq8lxxn/wgXole6SlBHHKKyZhNJoS+8= -cloud.google.com/go/vpcaccess v1.7.5 h1:XyL6hTLtEM/eE4F1GEge8xUN9ZCkiVWn44K/YA7z1rQ= -cloud.google.com/go/vpcaccess v1.7.5/go.mod h1:slc5ZRvvjP78c2dnL7m4l4R9GwL3wDLcpIWz6P/ziig= -cloud.google.com/go/vpcaccess v1.8.2 h1:nvrkqAjS2sorOu4YGCIXWz+Kk+5aAAdnaMD2tnsqeFg= -cloud.google.com/go/vpcaccess v1.8.2/go.mod h1:4yvYKNjlNjvk/ffgZ0PuEhpzNJb8HybSM1otG2aDxnY= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0 h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/webrisk v1.9.1 h1:Ssy3MkOMOnyRV5H2bkMQ13Umv7CwB/kugo3qkAX83Fk= -cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= -cloud.google.com/go/webrisk v1.9.4 h1:iceR3k0BCRZgf2D/NiKviVMFfuNC9LmeNLtxUFRB/wI= -cloud.google.com/go/webrisk v1.9.5 h1:251MvGuC8wisNN7+jqu9DDDZAi38KiMXxOpA/EWy4dE= -cloud.google.com/go/webrisk v1.9.5/go.mod h1:aako0Fzep1Q714cPEM5E+mtYX8/jsfegAuS8aivxy3U= -cloud.google.com/go/webrisk v1.10.2 h1:X7zSwS1mX2bxoZ30Ozh6lqiSLezl7RMBWwp5a3Mkxp4= -cloud.google.com/go/webrisk v1.10.2/go.mod h1:c0ODT2+CuKCYjaeHO7b0ni4CUrJ95ScP5UFl9061Qq8= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0 h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/websecurityscanner v1.6.1 h1:CfEF/vZ+xXyAR3zC9iaC/QRdf1MEgS20r5UR17Q4gOg= -cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= -cloud.google.com/go/websecurityscanner v1.6.4 h1:5Gp7h5j7jywxLUp6NTpjNPkgZb3ngl0tUSw6ICWvtJQ= -cloud.google.com/go/websecurityscanner v1.6.5 h1:YqWZrZYabG88TZt7364XWRJGhxmxhony2ZUyZEYMF2k= -cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ= -cloud.google.com/go/websecurityscanner v1.7.2 h1:8/4rfJXcyxozbfzI0lDFPcPShRE6bJ4HQwgDAG9J4oQ= -cloud.google.com/go/websecurityscanner v1.7.2/go.mod h1:728wF9yz2VCErfBaACA5px2XSYHQgkK812NmHcUsDXA= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0 h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -cloud.google.com/go/workflows v1.12.0 h1:cSUlx4PVV9O0vYCl+pHAUmu0996A7eN602d4wjjVHRs= -cloud.google.com/go/workflows v1.12.0/go.mod h1:PYhSk2b6DhZ508tj8HXKaBh+OFe+xdl0dHF/tJdzPQM= -cloud.google.com/go/workflows v1.12.3 h1:qocsqETmLAl34mSa01hKZjcqAvt699gaoFbooGGMvaM= -cloud.google.com/go/workflows v1.12.4 h1:uHNmUiatTbPQ4H1pabwfzpfEYD4BBnqDHqMm2IesOh4= -cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= -cloud.google.com/go/workflows v1.13.2 h1:jYIxrDOVCGvTBHIAVhqQ+P8fhE0trm+Hf2hgL1YzmK0= -cloud.google.com/go/workflows v1.13.2/go.mod h1:l5Wj2Eibqba4BsADIRzPLaevLmIuYF2W+wfFBkRG3vU= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/zipkin v0.1.2 h1:YqE293IZrKtqPnpwDPH/lOqTWD/s3Iwabycam74JV3g= -contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= -gioui.org v0.0.0-20210308172011-57750fc8a0a6 h1:K72hopUosKG3ntOPNG4OzzbuhxGuVf06fa2la1/H/Ho= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCqWCLp6Cifo= -github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= -github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v46.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v50.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v61.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v62.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v67.0.0+incompatible h1:SVBwznSETB0Sipd0uyGJr7khLhJOFRUEUb+0JgkCvDo= -github.com/Azure/azure-sdk-for-go v67.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.6/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNhEIfOy/pTGasLqzHIPHs= -github.com/Azure/go-autorest/autorest v0.11.8/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNhEIfOy/pTGasLqzHIPHs= -github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= -github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= -github.com/Azure/go-autorest/autorest/adal v0.9.10/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= -github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.2/go.mod h1:q98IH4qgc3eWM4/WOeR5+YPmBuy8Lq0jNRDwSM0CuFk= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.1/go.mod h1:JfDgiIO1/RPu6z42AdQTyjOoCM2MFhLqSBDvMEkDgcg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= -github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 h1:oVLqHXhnYtUwM89y9T1fXGaK9wTkXHgNp8/ZNMQzUxE= -github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= -github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= -github.com/IBM/sarama v1.40.1 h1:lL01NNg/iBeigUbT+wpPysuTYW6roHo6kc1QrffRf0k= -github.com/IBM/sarama v1.40.1/go.mod h1:+5OFwA5Du9I6QrznhaMHsuwWdWZNMjaBSIxEWEgKOYE= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= -github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= -github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14= -github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig/v3 v3.0.2 h1:wz22D0CiSctrliXiI9ZO3HoNApweeRGftyDN+BQa3B8= -github.com/Masterminds/vcs v1.13.1 h1:NL3G1X7/7xduQtA2sJLpVpfHTNBALVNSjob6KEjPXNQ= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OpenPeeDeeP/depguard v1.0.0 h1:k9QF73nrHT3nPLz3lu6G5s+3Hi8Je36ODr1F5gjAXXM= -github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= -github.com/Shopify/sarama v1.30.0 h1:TOZL6r37xJBDEMLx4yjB77jxbZYXPaDow08TSK6vIL0= -github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= -github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae h1:ePgznFqEG1v3AjMklnK8H7BSc++FDSo7xfK9K7Af+0Y= -github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= -github.com/Shopify/toxiproxy/v2 v2.5.0 h1:i4LPT+qrSlKNtQf5QliVjdP08GyAH8+BUIc9gT0eahc= -github.com/Shopify/toxiproxy/v2 v2.5.0/go.mod h1:yhM2epWtAmel9CB8r2+L+PCmhH6yH2pITaPAo7jxJl0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= -github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210609063737-0067dc6dcea2 h1:t/ces1/q8tuApSb+T5ajsu3wqkofUT43U1gpDYTPYME= -github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210609063737-0067dc6dcea2/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9 h1:7kQgkwGRoLzC9K0oyXdJo7nve/bynv/KwUsxbiTlzAM= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19 h1:iXUgAaqDcIUGbRoy2TdeofRG/j1zpGRSEmNK05T+bi8= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a h1:FTykHiUVgZkL0cdTplzjoDZnizgAqEo6riN3R2VYwg0= -github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b h1:doCpXjVwui6HUN+xgNsNS3SZ0/jUZ68Eb+mJRNOZfog= -github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= -github.com/alecthomas/kingpin/v2 v2.3.1 h1:ANLJcKmQm4nIaog7xdr/id6FM6zm5hHnfZrvtKPxqGg= -github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= -github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= -github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= -github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= -github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= -github.com/apache/arrow/go/v10 v10.0.1 h1:n9dERvixoC/1JjDmBcs9FPaEryoANa2sCgVFo6ez9cI= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0 h1:hqauxvFQxww+0mEU/2XHG6LT7eZternCZq+A5Yly2uM= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/arrow/go/v12 v12.0.0 h1:xtZE63VWl7qLdB0JObIXvvhGjoVNrQ9ciIHG2OK5cmc= -github.com/apache/arrow/go/v12 v12.0.1 h1:JsR2+hzYYjgSUkBSaahpqCetqZMr76djX80fF/DiJbg= -github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWMLpY67QwZ/WWw= -github.com/apache/arrow/go/v14 v14.0.2 h1:N8OkaJEOfI3mEZt07BIkvo4sC6XDbL+48MBPWO5IONw= -github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= -github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE= -github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= -github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs= -github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= -github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= -github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= -github.com/aws/aws-sdk-go v1.17.7 h1:/4+rDPe0W95KBmNGYCG+NUvdL8ssPYBMxL+aSCg6nIA= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= -github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= -github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.37.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.44.302 h1:ST3ko6GrJKn3Xi+nAvxjG3uk/V1pW8KC52WLeIxqqNk= -github.com/aws/aws-sdk-go v1.44.302/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250= -github.com/aws/aws-sdk-go-v2 v1.12.0/go.mod h1:tWhQI5N5SiMawto3uMAQJU5OUN/1ivhDDHq7HTsJvZ0= -github.com/aws/aws-sdk-go-v2 v1.14.0/go.mod h1:ZA3Y8V0LrlWj63MQAnRHgKf/5QB//LSZCPNWlWrNGLU= -github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= -github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= -github.com/aws/aws-sdk-go-v2/config v1.5.0/go.mod h1:RWlPOAW3E3tbtNAqTwvSW54Of/yP3oiZXMI0xfUdjyA= -github.com/aws/aws-sdk-go-v2/config v1.12.0/go.mod h1:GQONFVSDdG6RRho1C730SGNyDhS1kSTnxpOE76ptBqo= -github.com/aws/aws-sdk-go-v2/config v1.14.0/go.mod h1:GKDRrvsq/PTaOYc9252u8Uah1hsIdtor4oIrFvUNPNM= -github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= -github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= -github.com/aws/aws-sdk-go-v2/credentials v1.3.1/go.mod h1:r0n73xwsIVagq8RsxmZbGSRQFj9As3je72C2WzUIToc= -github.com/aws/aws-sdk-go-v2/credentials v1.7.0/go.mod h1:Kmq64kahHJtXfmnEwnvRKeNjLBqkdP++Itln9BmQerE= -github.com/aws/aws-sdk-go-v2/credentials v1.9.0/go.mod h1:PyHKqk/+tJuDY7T8R580S1j/AcSD+ODeUZ99CAUKLqQ= -github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= -github.com/aws/aws-sdk-go-v2/credentials v1.12.21/go.mod h1:O+4XyAt4e+oBAoIwNUYkRg3CVMscaIJdmZBOcPgJ8D8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.3.0/go.mod h1:2LAuqPx1I6jNfaGDucWfA2zqQCYCOMCDHiCOciALyNw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.9.0/go.mod h1:19SxQ+9zANyJCnNaoF3ovl8bFil4TaqCYEDdqNGKM+A= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0/go.mod h1:rwdUKJV5rm+vHu1ncD1iGDqahBEL8O0tBjVqo9eO2N0= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.3/go.mod h1:L72JSFj9OwHwyukeuKFFyTj6uFWE4AjB0IQp97bd9Lc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5/go.mod h1:2hXc8ooJqF2nAznsbJQIn+7h851/bu8GVC80OVTTqf8= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.1.0/go.mod h1:KdVvdk4gb7iatuHZgIkIqvJlWHBtjCJLUtD/uO/FkWw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0/go.mod h1:miRSv9l093jX/t/j+mBCaLqFHo9xKYzJ7DGm1BsGoJM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= -github.com/aws/aws-sdk-go-v2/internal/ini v1.1.1/go.mod h1:Zy8smImhTdOETZqfyn01iNOe0CNggVbPjCajyaz6Gvg= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.3/go.mod h1:N4dv+zawriMFZBO/6UKg3zt+XO6xWOQo1neAA0lFbo4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6/go.mod h1:o1ippSg3yJx5EuT4AOGXJCUcmt5vrcxla1cg6K1Q8Iw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= -github.com/aws/aws-sdk-go-v2/service/ecr v1.4.1/go.mod h1:FglZcyeiBqcbvyinl+n14aT/EWC7S1MIH+Gan2iizt0= -github.com/aws/aws-sdk-go-v2/service/ecr v1.13.0/go.mod h1:X9rkClmo0/dXh2fwvhkMoXR5zxirrzCqMgfU+Z0HIgs= -github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0/go.mod h1:4zYI85WiYDhFaU1jPFVfkD7HlBcdnITDE3QxDwy4Kus= -github.com/aws/aws-sdk-go-v2/service/ecr v1.17.18 h1:uiF/RI+Up8H2xdgT2GWa20YzxiKEalHieqNjm6HC3Xk= -github.com/aws/aws-sdk-go-v2/service/ecr v1.17.18/go.mod h1:DQtDYmexqR+z+B6HBCvY7zK/tuXKv6Zy/IwOXOK3eow= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.1/go.mod h1:eD5Eo4drVP2FLTw0G+SMIPWNWvQRGGTtIZR2XeAagoA= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.10.0/go.mod h1:wlxlU/f1AOpsYIxt86LyrztTAIhyp/6HRNHcZjLzHjg= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0/go.mod h1:IArQ3IBR00FkuraKwudKZZU32OxJfdTdwV+W5iZh3Y4= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.17 h1:bcQy5/dcJO8VQD+p0tDoIYdgEC3ch9f1/BNRES7XMug= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.17/go.mod h1:r1Vuka0kyzqN0sZm4lYTXf0Vhl+o/mTLq6vKpBBZYaQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1/go.mod h1:zceowr5Z1Nh2WVP8bf/3ikB41IZW59E4yIYbg+pC6mw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.6.0/go.mod h1:wTgFkG6t7jS/6Y0SILXwfspV3IXowb6ngsAlSajW0Kc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0/go.mod h1:rBDLgXDAwHOfxZKLRDl8OGTPzFDC+a2pLqNNj8+QwfI= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= -github.com/aws/aws-sdk-go-v2/service/sso v1.3.1/go.mod h1:J3A3RGUvuCZjvSuZEcOpHDnzZP/sKbhDWV2T1EOzFIM= -github.com/aws/aws-sdk-go-v2/service/sso v1.8.0/go.mod h1:AB6v3BedyhVRIbPQbJnUsBmtup2pFiikpp5n3YyB6Ac= -github.com/aws/aws-sdk-go-v2/service/sso v1.10.0/go.mod h1:m1CRRFX7eH3EE6w0ntdu+lo+Ph9VS7y8qRV/vdym0ZY= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV6hzJlL2JKD76wNNVzgQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= -github.com/aws/aws-sdk-go-v2/service/sts v1.6.0/go.mod h1:q7o0j7d7HrJk/vr9uUt3BVRASvcU7gYZB9PUgPiByXg= -github.com/aws/aws-sdk-go-v2/service/sts v1.13.0/go.mod h1:jQto17aC9pJ6xRa1g29uXZhbcS6qNT3PSnKfPShq4sY= -github.com/aws/aws-sdk-go-v2/service/sts v1.15.0/go.mod h1:E264g2Gl5U9KTGzmd8ypGEAoh75VmqyuA/Ox5O1eRE4= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= -github.com/aws/smithy-go v1.6.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.9.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.11.0/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= -github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= -github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20211215200129-69c85dc22db6/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221004211355-a250ad2ca1e3 h1:Ted/bR1N6ltMrASdwRhX1BrGYSFg3aeGMlK8GlgkGh4= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221004211355-a250ad2ca1e3/go.mod h1:m06KtrZgOloUaePAQMv+Ha8kRmTnKdozTHZrweepIrw= -github.com/bazelbuild/rules_go v0.49.0 h1:5vCbuvy8Q11g41lseGJDc5vxhDjJtfxr6nM/IC4VmqM= -github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= -github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c h1:+0HFd5KSZ/mm3JmhmrDukiId5iR6w4+BdFtfSy4yWIc= -github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE= -github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e h1:mWOqoK5jV13ChKf/aF3plwQ96laasTJgZi4f1aSOu+M= -github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= -github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= -github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= -github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00cee21/go.mod h1:Zlre/PVxuSI9y6/UV4NwGixQ48RHQDSPiUkofr6rbMU= -github.com/chrismellard/docker-credential-acr-env v0.0.0-20221002210726-e883f69e0206 h1:lG6Usi/kX/JBZzGz1H+nV+KwM97vThQeKunCbS6PutU= -github.com/chrismellard/docker-credential-acr-env v0.0.0-20221002210726-e883f69e0206/go.mod h1:1UmFRnmMnVsHwD+ZntmLkoVBB1ZLa6V+XXEbF6hZCxU= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= -github.com/chromedp/chromedp v0.9.2 h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw= -github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= -github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= -github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= -github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= -github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= -github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/cloudevents/conformance v0.2.0 h1:NvSXOKlagcsOWMEbi8U7Ex/0oQ4JZE1HQ45bnxYf2zk= -github.com/cloudevents/conformance v0.2.0/go.mod h1:rHKDwylBH89Rns6U3wL9ww8bg9/4GbwRCDNuyoC6bcc= -github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.4.1 h1:UHjY9+DJyjELyFA8vU/KHHXix1F1z7QLFskzdJZkP+0= -github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.13.0 h1:Mf5y5GYVusfOpPQsKHOvr9c3Y76fZnSZzuZo+LQr/aU= -github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.13.0/go.mod h1:vgBrMXc1h8htR8PUlGViBcNEkri4fw98nY8Tqsgdtfs= -github.com/cloudevents/sdk-go/v2 v2.13.0/go.mod h1:xDmKfzNjM8gBvjaF8ijFjM1VYOVUEeUfapHMUX1T5To= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= -github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= -github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c h1:2zRrJWIt/f9c9HhNHAgrRgq0San5gRRUJTBXLkchal0= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= -github.com/containerd/containerd v1.6.0/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41 h1:kIFnQBO7rQ0XkMe6xEwbybYHBEaWmh/f++laI6Emt7M= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.6.4/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= -github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= -github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= -github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac= -github.com/containerd/stargz-snapshotter/estargz v0.11.1/go.mod h1:6VoPcf4M1wvnogWxqc4TqBWWErCS+R+ucnPZId2VbpQ= -github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= -github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de h1:dlfGmNcE3jDAecLqwKPMNX6nk2qh1c1Vg1/YTzpOOF4= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= -github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= -github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= -github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= -github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= -github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= -github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c h1:/ovYnF02fwL0kvspmy9AuyKg1JhdTRUgPw4nUxd9oZM= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= -github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07 h1:UHFGPvSxX4C4YBApSPvmUfL8tTvWLj2ryqvT9K4Jcuk= -github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f h1:7uSNgsgcarNk4oiN/nNkO0J7KAjlsF5Yv5Gf/tFdHas= -github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4 h1:CVAqftqbj+exlab+8KJQrE+kNIVlQfJt58j4GxCMF1s= -github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00 h1:FHpbUtp2K8X53/b4aFNj4my5n+i3x+CQCZWNuHWH/+E= -github.com/cznic/lldb v1.1.0 h1:AIA+ham6TSJ+XkMe8imQ/g8KPzMUVWAwqUQQdtuMsHs= -github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369 h1:XNT/Zf5l++1Pyg08/HV04ppB0gKxAqtZQBRYiYrUuYk= -github.com/cznic/ql v1.2.0 h1:lcKp95ZtdF0XkWhGnVIXGF8dVD2X+ClS08tglKtf+ak= -github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 h1:hxuZop6tSoOi0sxFzoGGYdRqNrPubyaIf9KoBG9tPiE= -github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA= -github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc h1:YKKpTb2BrXN2GYyGaygIdis1vXbE7SSAG9axGWIMClg= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/daixiang0/gci v0.2.9/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= -github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= -github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU= -github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ= -github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/dave/kerr v0.0.0-20170318121727-bc25dd6abe8e/go.mod h1:qZqlPyPvfsDJt+3wHJ1EvSXDuVjFTK0j2p/ca+gtsb8= -github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= -github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMphB1eRx7xB1njzL3fuMdWRN8HtVzoUOItHMwv5c= -github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/deislabs/oras v0.8.1 h1:If674KraJVpujYR00rzdi0QAmW4BxzMJPVAZJKuhQ0c= -github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3 h1:tkum0XDgfR0jcVVXuTsYv/erY2NnEDqwRojbxR1rBYA= -github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= -github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba h1:p6poVbjHDkKa+wtC8frBMwQtT3BmqGYBjzMwJ63tuR4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654 h1:XOPLOMn/zT4jIgxfxSsoXPxkrzz0FaCHwp33x5POJ+Q= -github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77 h1:iRnqZBF0a1hoOOjOdPKf+IxqlJZOas7A48j77RAc7Yg= -github.com/dgryski/go-lttb v0.0.0-20230207170358-f8fc36cdbff1 h1:dxwR3CStJdJamsIoMPCmxuIfBAPTgmzvFax+MvFav3M= -github.com/dgryski/go-lttb v0.0.0-20230207170358-f8fc36cdbff1/go.mod h1:UwftcHUI/qTYvLAxrWmANuRckf8+08O3C3hwStvkhDU= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= -github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I= -github.com/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E= -github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= -github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4= -github.com/docker/cli v20.10.20+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+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 v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.20+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= -github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q= -github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0= -github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= -github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 h1:8yY/I9ndfrgrXUbOGObLHKBR4Fl3nZXwM2c7OYTT8hM= -github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= -github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8= -github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/emicklei/go-restful v2.15.0+incompatible h1:8KpYO/Xl/ZudZs5RNOEhWMBY4hmzlZhhRd9cu+jrZP4= -github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= -github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= -github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= -github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= -github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= -github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= -github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= -github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= -github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flowstack/go-jsonschema v0.1.1 h1:dCrjGJRXIlbDsLAgTJZTjhwUJnnxVWl1OgNyYh5nyDc= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fsouza/fake-gcs-server v1.7.0 h1:Un0BXUXrRWYSmYyC1Rqm2e2WJfTPyDy/HGMz31emTi8= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= -github.com/getkin/kin-openapi v0.61.0 h1:6awGqF5nG5zkVpMsAih1QH4VgzS8phTxECUWIFo7zko= -github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= -github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540 h1:djv/qAomOVj8voCHt0M0OYwR/4vfDq1zNKSPKjJCexs= -github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= -github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0 h1:UlZlgrvvmT/58o573ot7NFw0vZasZ5I6bcIft/oMdgg= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= -github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= -github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.10 h1:5BHISBAXOc/aJK25irLZnx2D3s6WyYaY9D4gmuz9fdE= -github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.7 h1:Lcq+o0mSwCLKACMxZhreVHigB9ebghJ/lrmeaqASbjo= -github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= -github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= -github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls= -github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= -github.com/go-openapi/runtime v0.19.16 h1:tQMAY5s5BfmmCC31+ufDCsGrr8iO1A8UIdYfDo5ADvs= -github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= -github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc= -github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28= -github.com/go-openapi/spec v0.20.2/go.mod h1:RW6Xcbs6LOyWLU/mXGdzn2Qc+3aj+ASfI7rvSZh1Vls= -github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= -github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= -github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= -github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= -github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8= -github.com/go-openapi/validate v0.19.11 h1:8lCr0b9lNWKjVjW/hSZZvltUy+bULl7vbnCTsOzlhPo= -github.com/go-openapi/validate v0.19.11/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= -github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21 h1:wP6mXeB2V/d1P1K7bZ5vDUO3YqEzcvOREOxZPEu3gVI= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= -github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= -github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= -github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= -github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= -github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4 h1:vF83LI8tAakwEwvWZtrIEx7pOySacl2TOxx6eXk4ePo= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= -github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w= -github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= -github.com/golangci/go-tools v0.0.0-20190318055746-e32c54105b7c h1:/7detzz5stiXWPzkTlPTzkBEIIE4WGpppBJYjKqBiPI= -github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= -github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= -github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98 h1:0OkFarm1Zy2CjCiDKfK9XHgmc2wbDlRMD2hD8anAJHU= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.17.2-0.20190909185456-6163a8a79084 h1:Z4/yXcGr9zrQrcvHkC8f3agyK1dwt/t6zC/8gi6X64Q= -github.com/golangci/golangci-lint v1.43.0/go.mod h1:VIFlUqidx5ggxDfQagdvd9E67UjMXtTHBkBQ7sHoC5Q= -github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547 h1:fUdgm/BdKvwOHxg5AhNbkNRp2mSy8sxTXyBVs/laQHo= -github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217 h1:En/tZdwhAn0JNwLuXzP3k2RVtMqMmOEK7Yu/g3tmtJE= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= -github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= -github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= -github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450 h1:7xqw01UYS+KCI25bMrPxwNYkSns2Db1ziQPpVq99FpE= -github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995 h1:f5gsjBiF9tRRVomCvrkGMMWI8W1f2OBFar2c5oakAP0= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZPbFy2P7jH5LKJ3La+0ZeknkkmrSgqb0= -github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac h1:Q0Jsdxl5jbxouNs1TQYt0gxesYMU4VXRbsTlgDloZ50= -github.com/gonum/diff v0.0.0-20181124234638-500114f11e71 h1:BE6g8oinc3Ek2elIHq+uDOiZgX3/ODi+EerJ48yrrKc= -github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 h1:EvokxLQsaaQjcWVWSV38221VAK7qc2zhaO17bKys/18= -github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2 h1:GUSkTcIe1SlregbHNUKbYDhBsS8lNgYfIp4S4cToUyU= -github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 h1:8jtTdc+Nfj9AR+0soOeia9UZSvYBvETVHZrugUowJ7M= -github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9 h1:7qnwS9+oeSiOIsiUMajT+0R7HR6hw5NegnKPmn/94oI= -github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55 h1:Ajwn2ENgC/pKtVat0LEHEWNa4a4VGyYJ1feGSccOzFU= -github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9 h1:V2IgdyerlBa/MxaEFRbV5juy/C3MGdj4ePi+g6ePIp4= -github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b h1:fbskpz/cPqWH8VqkQ7LJghFkl2KPAiIFUHrTJ2O3RGk= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M= -github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= -github.com/google/cel-go v0.12.7 h1:jM6p55R0MKBg79hZjn1zs2OlrywZ1Vk00rxVvad1/O0= -github.com/google/cel-go v0.12.7/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= -github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= -github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= -github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= -github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= -github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= -github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220414154538-570ba6c88a50/go.mod h1:m7mMYMlUraMy65yWp4AXkMgousS5LFPYcvI19yjz6W0= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230209165335-3624968304fd h1:hQf//Ak0trkoqnm94i9mw00d7axUwfK92hMxslxNKYc= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230209165335-3624968304fd/go.mod h1:x5fIlj5elU+/eYF60q4eASMQ9kDc+GMFa7UU9M3mFFw= -github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220414143355-892d7a808387/go.mod h1:QOryQrrP9Uq/1w9F7WOWWhK2/gHXg7F0i3J/hPG6yQA= -github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20230209165335-3624968304fd h1:AQZlI371LcvBYY/7Q55TjxrpZJs6wtEXMw4Wq38XLy8= -github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20230209165335-3624968304fd/go.mod h1:6pjZpt+0dg+Z0kUEn53qLtD57raiZo/bqWzsuX6dDjo= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github/v27 v27.0.6 h1:oiOZuBmGHvrGM1X9uNUAUlLgp5r1UUO/M/KnbHnLRlQ= -github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= -github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0= -github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9 h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk= -github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= -github.com/google/go-pkcs11 v0.3.0 h1:PVRnTgtArZ3QQqTGtbtjtnIkzl2iY2kt24yqbrf7td8= -github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3 h1:/o5e44nTD/QEEiWPGSFT3bSqcq3Qg7q27N9bv4gKh5M= -github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= -github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= -github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/cloud-bigtable-clients-test v0.0.2 h1:S+sCHWAiAc+urcEnvg5JYJUOdlQEm/SEzQ/c/IdAH5M= -github.com/googleapis/cloud-bigtable-clients-test v0.0.2/go.mod h1:mk3CrkrouRgtnhID6UZQDK3DrFFa7cYCAJcEmNsHYrY= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= -github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= -github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo= -github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= -github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= -github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db h1:UxmGBzaBcWDQuQh9E1iT1dWKQFbizZ+SpTd1EL4MSqs= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= -github.com/hashicorp/consul/api v1.22.0/go.mod h1:zHpYgZ7TeYqS6zaszjwSt128OwESRpnhU9aGa6ue3Eg= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= -github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= -github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= -github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= -github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE= -github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/influxdata/influxdb-client-go/v2 v2.9.0 h1:1Ejxpt+cpWkadefxd5xvVx7pFgFaafdNp1ItfHzKRW4= -github.com/influxdata/influxdb-client-go/v2 v2.9.0/go.mod h1:x7Jo5UHHl+w8wu8UnGiNobDDHygojXwJX4mx7rXGKMk= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= -github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= -github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= -github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= -github.com/jackc/pgx v3.2.0+incompatible h1:0Vihzu20St42/UDsvZGdNE6jak7oi/UOeMzwMPHkgFY= -github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= -github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= -github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= -github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= -github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= -github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= -github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= -github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= -github.com/jcmturner/gokrb5/v8 v8.4.3 h1:iTonLeSJOn7MVUtyMT+arAn5AKAPrkilzhGw8wE/Tq8= -github.com/jcmturner/gokrb5/v8 v8.4.3/go.mod h1:dqRwJGXznQrzw6cWmyo6kH+E7jksEQG/CyVWsJEsJO0= -github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= -github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joefitzgerald/rainbow-reporter v0.1.0 h1:AuMG652zjdzI0YCCnXAqATtRBpGXMcAnrajcaTrSeuo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= -github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= -github.com/kshvakov/clickhouse v1.3.5 h1:PDTYk9VYgbjPAWry3AoDREeMgOVUFij6bh6IjlloHL0= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.2.1 h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac h1:+2b6iGRJe3hvV/yVXrd41yVEjxuFHxasJqDhkIjS4gk= -github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= -github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= -github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k= -github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb h1:w1g9wNDIE/pHSTmAaUhv4TZQuPBS6GV3mMz5hkgziIU= -github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1 h1:erE0rdztuaDq3bpGifD95wfoPrSZc95nGA6tbiNYh6M= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1 h1:keaAo8hRuAT0O3DfJ/wM3rufbAjGeJ1lAtWZHDjKGB0= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= -github.com/lyft/protoc-gen-star/v2 v2.0.3 h1:/3+/2sWyXeMLzKd1bX+ixWKgEMsULrIivpDsuaF441o= -github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4 h1:sIXJOMrYnQZJu7OB7ANSF4MYri2fTEGIsRLz6LwI4xE= -github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= -github.com/marstr/guid v1.1.0 h1:/M4H/1G4avsieL6BbUwCOBzulmoeKVP5ux/3mQNnbyI= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd h1:HvFwW+cm9bCbZ/+vuGNq7CRWXql8c0y8nGeYpqmpvmk= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= -github.com/mattn/go-shellwords v1.0.9 h1:eaB5JspOwiKKcHdqcjbfe5lA9cNn/4NRRtddXJCimqk= -github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= -github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= -github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= -github.com/miekg/dns v1.1.17 h1:BhJxdA7bH51vKFZSY8Sn9pR7++LREvg0eYFzHA452ew= -github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= -github.com/mikefarah/yaml/v2 v2.4.0 h1:eYqfooY0BnvKTJxr7+ABJs13n3dg9n347GScDaU2Lww= -github.com/mikefarah/yq/v2 v2.4.1 h1:tajDonaFK6WqitSZExB6fKlWQy/yCkptqxh2AXEe3N4= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= -github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8Ma8CLF2Zzgjfx95gs3/GN3vYAPpo= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= -github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40 h1:Q0XH6Ql1+Z6YbUKyWyI0sD8/9yH0U8x86yA8LuWMJwY= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8 h1:P48LjvUQpTReR3TQRbxSeSBsMXzfK0uol7eRcr7VBYQ= -github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= -github.com/ncw/swift v1.0.47 h1:4DQRPj35Y41WogBxyhOXlrI37nzGlyEcsforeudyYPQ= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 h1:58+kh9C6jJVXYjt8IE48G2eWl6BjwU5Gj0gqY84fy78= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= -github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= -github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= -github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= -github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= -github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= -github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= -github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700 h1:eNUVfm/RFLIi1G7flU5/ZRTHvd4kcVuzfRnL6OFlzCI= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39 h1:H7DMc6FAjgwZZi8BRqjrAAHWoqEr5e5L6pS4V0ezet4= -github.com/openshift/api v0.0.0-20230522130544-0eef84f63102 h1:DvXc9rkFXM8Q4Gva6MYoenwnvgX1Ij1cLkewLb91D5Q= -github.com/openshift/api v0.0.0-20230522130544-0eef84f63102/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= -github.com/openshift/build-machinery-go v0.0.0-20220913142420-e25cf57ea46d h1:RR4ah7FfaPR1WePizm0jlrsbmPu91xQZnAsVVreQV1k= -github.com/openshift/build-machinery-go v0.0.0-20220913142420-e25cf57ea46d/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= -github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb h1:Nij5OnaECrkmcRQMAE9LMbQXPo95aqFnf+12B7SyFVI= -github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb/go.mod h1:Rhb3moCqeiTuGHAbXBOlwPubUMlOZEkrEWTRjIF3jzs= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= -github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA= -github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= -github.com/operator-framework/api v0.1.1 h1:DbfxRJUPMQlQW6nbfoNzWLxv1rIv13Gt8GbsF2aglFk= -github.com/operator-framework/operator-lib v0.11.0/go.mod h1:RpyKhFAoG6DmKTDIwMuO6pI3LRc8IE9rxEYWy476o6g= -github.com/operator-framework/operator-registry v1.6.1 h1:Ow0Ko9DRIZ4xvH55vFAslcTy6A9FhlIeXvm+FhyRd84= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc= -github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 h1:o59bHXu8Ejas8Kq6pjoVJQ9/neN66SM8AKh6wI42BBs= -github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= -github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= -github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml/v2 v2.0.0-beta.2 h1:f/g66OWmYXmVnYL3UAhqpM9YuWKFR2vjYfFNSDQcHPQ= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/phpdave11/gofpdf v1.4.2 h1:KPKiIbfwbvC/wOncwhrpRdXVj2CZTCFlw4wnoyjtHfQ= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13 h1:o61duiW8M9sMlkVXWlvP92sZJtGKENvW3VExs6dZukQ= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= -github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= -github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM= -github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM= -github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= -github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/alertmanager v0.25.0/go.mod h1:MEZ3rFVHqKZsw7IcNS/m4AWZeXThmJhumpiWR4eHU/w= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= -github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.47.0 h1:tIJJKZGlmrMVsvIt6rMfB8he7CRHEc8ZxS5ubcZtbkM= -github.com/prometheus/prometheus v0.47.0/go.mod h1:J/bmOSjgH7lFxz2gZhrWEZs2i64vMS+HIuZfmYNhJ/M= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= -github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c h1:JoUA0uz9U0FVFq5p4LjEq4C0VgQ0El320s3Ms0V4eww= -github.com/rabbitmq/amqp091-go v1.1.0 h1:qx8cGMJha71/5t31Z+LdPLdPrkj/BvD38cqC3Bi1pNI= -github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM= -github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA= -github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs= -github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/sclevine/spec v1.2.0 h1:1Jwdf9jSfDl9NVmt8ndHqbTZ7XCCPbh1jI3hkDBHVYA= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/serverlessworkflow/sdk-go/v2 v2.4.2 h1:dqRa/i5J885rk0bGIXzUVLwEFfRWB9gpQfOdXlbejsI= -github.com/serverlessworkflow/sdk-go/v2 v2.4.2/go.mod h1:WGJR0YhXp035Y/toMKwHeIT5/EDEkDEDozn6VIGSUqI= -github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7 h1:80VN+vGkqM773Br/uNNTSheo3KatTgV8IpjIKjvVLng= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= -github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.3.3 h1:p5gZEKLYoL7wh8VrJesMaYeNxdEd1v3cb4irOk9zB54= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518 h1:iD+PFTQwKEmbwSdwfvP5ld2WEI/g7qbdhmHJ2ASfYGs= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A= -github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d h1:X4+kt6zM/OVO6gbJdAfJR60MGPsqCzbtXNnjoGqdfAs= -github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807 h1:LUsDduamlucuNnWcaTbXQ6aLILFcLXADpOzeEH3U+OI= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8 h1:zLV6q4e8Jv9EHjNg/iHfzwDkCve6Ua5jCygptrtXHvI= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec h1:AmoEvWAO3nDx1MEcMzPh+GzOOIA5Znpv6++c7bePPY0= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= -github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3 h1:pcQGQzTwCg//7FgVywqge1sW9Yf8VMsMdG58MI5kd8s= -github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= -github.com/tsenart/vegeta/v12 v12.11.1 h1:Rbwe7Zxr7sJ+BDTReemeQalYPvKiSV+O7nwmUs20B3E= -github.com/tsenart/vegeta/v12 v12.11.1/go.mod h1:swiFmrgpqj2llHURgHYFRFN0tfrIrlnspg01HjwOnSQ= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= -github.com/ultraware/funlen v0.0.1 h1:UeC9tpM4wNWzUJfan8z9sFE4QCzjjzlCZmuJN+aOkH0= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/fasthttp v1.2.0 h1:dzZJf2IuMiclVjdw0kkT+f9u4YdrapbNyGAN47E/qnk= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/quicktemplate v1.1.1 h1:C58y/wN0FMTi2PR0n3onltemfFabany53j7M6SDDB8k= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= -github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= -github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= -github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68= -github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= -github.com/wavesoftware/go-ensure v1.0.0 h1:6X3gQL5psBWwtu/H9a+69xQ+JGTUELaLhgOB/iB3AQk= -github.com/wavesoftware/go-ensure v1.0.0/go.mod h1:K2UAFSwMTvpiRGay/M3aEYYuurcR8S4A6HkQlJPV8k4= -github.com/xanzy/go-gitlab v0.15.0 h1:rWtwKTgEnXyNUGrOArN7yyc3THRkpYcKXIXia9abywQ= -github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= -github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc= -github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= -github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= -github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 h1:j2hhcujLRHAg872RWAV5yaUrEjHEObwDv3aImCaNLek= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= -github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs= -go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8= -go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M= -go.einride.tech/aip v0.68.0 h1:4seM66oLzTpz50u4K1zlJyOXQ3tCzcJN7I22tKkjipw= -go.einride.tech/aip v0.68.0/go.mod h1:7y9FF8VtPWqpxuAxl0KQWqaULxW4zFIesD6zF5RIHHg= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= -go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= -go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= -go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= -go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k= -go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= -go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= -go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= -go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= -go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0= -go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= -go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= -go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= -go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= -go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4= -go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= -go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= -go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= -go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= -go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= -go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= -go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao= -go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= -go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= -go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.etcd.io/etcd/pkg/v3 v3.5.5/go.mod h1:6ksYFxttiUGzC2uxyqiyOEvhAiD0tuIqSZkX3TyPdaE= -go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= -go.etcd.io/etcd/pkg/v3 v3.5.7/go.mod h1:kcOfWt3Ov9zgYdOiJ/o1Y9zFfLhQjylTgL4Lru8opRo= -go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM= -go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs= -go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= -go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= -go.etcd.io/etcd/raft/v3 v3.5.5/go.mod h1:76TA48q03g1y1VpTue92jZLr9lIHKUNcYdZOOGyx8rI= -go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= -go.etcd.io/etcd/raft/v3 v3.5.7/go.mod h1:TflkAb/8Uy6JFBxcRaH2Fr6Slm9mCPVdI2efzxY96yU= -go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA= -go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc= -go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= -go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= -go.etcd.io/etcd/server/v3 v3.5.5/go.mod h1:rZ95vDw/jrvsbj9XpTqPrTAB9/kzchVdhRirySPkUBc= -go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= -go.etcd.io/etcd/server/v3 v3.5.7/go.mod h1:gxBgT84issUVBRpZ3XkW1T55NjOb4vZZRI4wVvNhf4A= -go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg= -go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo= -go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= -go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= -go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= -go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= -go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI= -go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= -go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0014/go.mod h1:BRvDrx43kiSoUx3mr7SoA7h9B8+OY99mUK+CZSQFWW4= -go.opentelemetry.io/collector/semconv v0.81.0/go.mod h1:TlYPtzvsXyHOgr5eATi43qEMqwSmIziivJB2uctKswo= -go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= -go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 h1:ZOLJc06r4CB42laIXg/7udr0pbZyuAihN10A/XuiQRY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= -go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= -go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= -go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= -go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= -go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= -go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= -go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= -go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= -go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= -go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= -go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g= -golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= -golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa h1:efT73AJZfAAUV7SOip6pWGkwJDzIGiKBZGVzHYa+ve4= -golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= -golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= -golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= -google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= -google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= -google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= -google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= -google.golang.org/api v0.150.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg= -google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk= -google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= -google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= -google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= -google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= -google.golang.org/api v0.215.0 h1:jdYF4qnyczlEz2ReWIsosNLDuzXyvFHJtI5gcr0J7t0= -google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8 h1:Cpp2P6TPjujNoC5M2KHY6g7wfyLYfIWRZaSdIKfDasA= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:CCviP9RmpZ1mxVr8MUjCnSiY09IbAXZxhLE6EhHIdPU= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= -google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= -google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= -google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= -google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f/go.mod h1:Yo94eF2nj7igQt+TiJ49KxjIH8ndLYPZMIRSiRcEbg0= -google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:E5//3O5ZIG2l71Xnt+P/CYUY8Bxs8E7WMoZ9tlcMbAY= -google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231009173412-8bfb1ae86b6c h1:9tZedXBlwql0v/dLZx1E4Rcz9ESc8j1KZk71903wKEg= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:itlFWGBbEyD32PUeJsTG8h8Wz7iJXfVK4gt1EJ+pAG0= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405 h1:o4S3HvTUEXgRsNSUQsALDVog0O9F/U1JJlHmmUN8Uas= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78 h1:YqFWYZXim8bG9v68xU8WjTZmYKb5M5dMeSOWIp6jogI= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20241223144023-3abc09e42ca8 h1:qlXhWiX84AGgaN7LuORWBEQCCTqj3szNbh2am45O3W8= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:bLYPejkLzwgJuAHlIk1gdPOlx9CUYXLZi2rZxL/ursM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0= -gopkg.in/imdario/mergo.v0 v0.3.7 h1:QDotlIZtaO/p+Um0ok18HRTpq5i5/SAk/qprsor+9c8= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= -gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -helm.sh/helm/v3 v3.1.2 h1:VpNzaNv2DX4aRnOCcV7v5Of+XT2SZrJ8iOQ25AGKOos= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= -k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= -k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= -k8s.io/apiextensions-apiserver v0.26.5/go.mod h1:Olsde7ZNWnyz9rsL13iXYXmL1h7kWujtKeC3yWVCDPo= -k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= -k8s.io/apiextensions-apiserver v0.27.6/go.mod h1:AVNlLYRrESG5Poo6ASRUhY2pvoKPcNt8y/IuZ4lx3o8= -k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y= -k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= -k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/apiserver v0.26.5/go.mod h1:OSbw98Y1bDSbA2izYIKqhi10vb4KWP9b4siiCRFkBVE= -k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= -k8s.io/apiserver v0.27.6 h1:r/eHN8r3lG2buggHrVMy++kKhHlHn1HWSX1dqDtes54= -k8s.io/apiserver v0.27.6/go.mod h1:Xeo9OEXn2kDLK5pqspjdXQx7YKgDyKSpwIB4p0BmpAQ= -k8s.io/apiserver v0.27.16 h1:s3+lMqISTj5l/ZH/BvhdbiMfIoTF3/lrAN99BHccLmk= -k8s.io/apiserver v0.27.16/go.mod h1:xwxM8/bcAtgkWqbsGwMQjImIC5Jik7a4pHRptEDqQf0= -k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M= -k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY= -k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= -k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= -k8s.io/apiserver v0.31.6 h1:FEhEGLsz1PbMOHeQZDbOUlMh36zRZbjgKwJCoMhdGmw= -k8s.io/apiserver v0.31.6/go.mod h1:dpFh+xqFQ02O8vLYCIqoiV7sJIpZsUULeNuag6Y9HGo= -k8s.io/cli-runtime v0.17.3 h1:0ZlDdJgJBKsu77trRUynNiWsRuAvAVPBNaQfnt/1qtc= -k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= -k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= -k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= -k8s.io/code-generator v0.26.5/go.mod h1:iWTVFxfBX+RYe0bXjKqSM83KJF8eimor/izQInvq/60= -k8s.io/code-generator v0.27.1/go.mod h1:iWtpm0ZMG6Gc4daWfITDSIu+WFhFJArYDhj242zcbnY= -k8s.io/code-generator v0.27.2/go.mod h1:DPung1sI5vBgn4AGKtlPRQAyagj/ir/4jI55ipZHVww= -k8s.io/code-generator v0.27.6 h1:1zkSDvylcA11s91aYg5U7fZ24EXMZ+KIDOj/Z3Ti4c8= -k8s.io/code-generator v0.27.6/go.mod h1:DPung1sI5vBgn4AGKtlPRQAyagj/ir/4jI55ipZHVww= -k8s.io/code-generator v0.27.16 h1:nDZ6TL+hyEczXIlts1WCz57F09zDC1Xs/UMg0X+QvY0= -k8s.io/code-generator v0.27.16/go.mod h1:NmuMGweDQC7Ewx+c8zgbtVPLsy5r5Rs/+nQ7kuBwNbI= -k8s.io/code-generator v0.30.0 h1:3VUVqHvWFSVSm9kqL/G6kD4ZwNdHF6J/jPyo3Jgjy3k= -k8s.io/code-generator v0.30.0/go.mod h1:mBMZhfRR4IunJUh2+7LVmdcWwpouCH5+LNPkZ3t/v7Q= -k8s.io/code-generator v0.31.0 h1:w607nrMi1KeDKB3/F/J4lIoOgAwc+gV9ZKew4XRfMp8= -k8s.io/code-generator v0.31.0/go.mod h1:84y4w3es8rOJOUUP1rLsIiGlO1JuEaPFXQPA9e/K6U0= -k8s.io/code-generator v0.31.6 h1:CX4/NGV5UIdt7+nYG/G4+eGHOvcXAlKWswUhPPOtPtc= -k8s.io/code-generator v0.31.6/go.mod h1:vbqDrvP5hJJ5S/jzBtyMJoH5kJBWZMo/DZwMYiOQniE= -k8s.io/component-base v0.26.5/go.mod h1:wvfNAS05EtKdPeUxFceo8WNh8bGPcFY8QfPhv5MYjA4= -k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= -k8s.io/component-base v0.27.6/go.mod h1:NvjLtaneUeb0GgMPpCBF+4LNB9GuhDHi16uUTjBhQfU= -k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= -k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= -k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= -k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= -k8s.io/component-base v0.31.6 h1:FgI25PuZtCp2n7AFpOaDpMQOLieFdrpAbpeoZu7VhDI= -k8s.io/component-base v0.31.6/go.mod h1:aVRrh8lAI1kSShFmwcKLhc3msQoUcmFWPBDf0sXaISM= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 h1:iu3o/SxaHVI7tKPtkGzD3M9IzrE21j+CUKH98NQJ8Ms= -k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= -k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kms v0.26.5/go.mod h1:AYuV9ZebRhr6cb1eT9L6kZVxvgIUxmE1Fe6kPhqYvuc= -k8s.io/kms v0.27.2/go.mod h1:dahSqjI05J55Fo5qipzvHSRbm20d7llrSeQjjl86A7c= -k8s.io/kms v0.27.6 h1:0IWDsxoget7Gs4zzMAY+y7dwNaGvwlAvS2XQVuFECU0= -k8s.io/kms v0.27.6/go.mod h1:9YQuCFa+n88RWokHkl+4RHFQ9DATSip/ihBqxlDUBuw= -k8s.io/kms v0.27.16 h1:Zso2+ixKQzz/N9b8q9MrFKHv2Fu7jb+0Zvu+iLWAUME= -k8s.io/kms v0.27.16/go.mod h1:BQf/ALdGhPhqoc1q81A7WdWpjrZ6jCSfePCNecz1AW8= -k8s.io/kms v0.30.0 h1:ZlnD/ei5lpvUlPw6eLfVvH7d8i9qZ6HwUQgydNVks8g= -k8s.io/kms v0.30.0/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4= -k8s.io/kms v0.31.0 h1:KchILPfB1ZE+ka7223mpU5zeFNkmb45jl7RHnlImUaI= -k8s.io/kms v0.31.0/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/kms v0.31.6 h1:p7OY+9Hp8nPtgzm0vT9TrERNigQQSu8tkgWqn+GvB2w= -k8s.io/kms v0.31.6/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/kube-aggregator v0.17.3 h1:U7U/XHnKwQlvFmsEE6ubpjF0Y4AVhKtXo+9I3d0L6rY= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= -k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/kubectl v0.17.3 h1:9HHYj07kuFkM+sMJMOyQX29CKWq4lvKAG1UIPxNPMQ4= -k8s.io/kubernetes v1.13.0 h1:qTfB+u5M92k2fCCCVP2iuhgwwSOv1EkAkvQY1tQODD8= -k8s.io/metrics v0.17.3 h1:IqXkNK+5E3vnobFD923Mn1QJEt3fb6+sK0wIjtBzOvw= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/caching v0.0.0-20220412163508-8b5c244b8182/go.mod h1:BFtnxIjI27VMV52u4vHhplij9j5PbQRXFlDMv7EMjbM= -knative.dev/caching v0.0.0-20231017130712-54d0758671ef h1:92Gn5HUcgMJ78mbSpkCfUxrCTHHZSnvjURk0YRCbUqo= -knative.dev/caching v0.0.0-20231017130712-54d0758671ef/go.mod h1:plGN+mIBKRtVxZ0vQeZ3Gt02RIaj0niwIMnQNkQHycw= -knative.dev/hack v0.0.0-20230417170854-f591fea109b3/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q= -knative.dev/hack v0.0.0-20231016131700-2c938d4918da h1:xy+fvuz2LDOMsZ5UwXRaMF70NYUs9fsG+EF5/ierYBg= -knative.dev/hack v0.0.0-20231016131700-2c938d4918da/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q= -knative.dev/hack/schema v0.0.0-20210806075220-815cd312d65c h1:YqFCmijfROO3rzIO8u1EMKZXBwAFJMmIoTXcr6wdBy8= -knative.dev/hack/schema v0.0.0-20231016131700-2c938d4918da h1:euBj0+2eY7BryoQe6aVg6R40dkbsGHULu6wjBsB3Vf8= -knative.dev/hack/schema v0.0.0-20231016131700-2c938d4918da/go.mod h1:3pWwBLnTZSM9psSgCAvhKOHIPTzqfEMlWRpDu6IYhK0= -knative.dev/pkg v0.0.0-20230525143525-9bda38b21643 h1:DoGHeW3ckr509v87NcYSSuRHEnxKIxyJxWrrDO/71CY= -knative.dev/pkg v0.0.0-20230525143525-9bda38b21643/go.mod h1:dqC6IrvyBE7E+oZocs5PkVhq1G59pDTA7r8U17EAKMk= -knative.dev/reconciler-test v0.0.0-20210915181908-49fac7555086 h1:IAM7f2XCCfxwH9WODJ3+Puv0lrdK5IhqQloYaO4lfvg= -knative.dev/reconciler-test v0.0.0-20231024072442-5fb93a792b99 h1:RyJ5EZ0XMhTn4CdjI355ceeZmjpPhz4edMu2XRC67bA= -knative.dev/reconciler-test v0.0.0-20231024072442-5fb93a792b99/go.mod h1:ojrPzMaQ7FugThq5SAG3mF1+8/N6gM8b/gFM3kHUXJU= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1 h1:Q8/Cpi36V/QBfuQaFVeisEBs3WqoGAJprZzmf7TfEYI= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= -modernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1 h1:dkRh86wgmq/bJu2cAS2oqBCz/KsMZU7TUM4CibQ7eBs= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1 h1:ko32eKt3jf7eqIkCgPAeHMBXw3riNSLhl2f3loEF7o8= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/sqlite v1.18.2 h1:S2uFiaNPd/vTAP/4EmyY8Qe2Quzu26A2L1e25xRNTio= -modernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/tcl v1.13.2 h1:5PQgL/29XkQ9wsEmmNPjzKs+7iPCaYqUJAhzPvQbjDA= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34 h1:duVSyluuJA+u0BnkcLR01smoLrGgDTfWt5c8ODYG8fU= -pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U= -pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= -pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= -rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37/go.mod h1:vfnxT4FXNT8eGvO+xi/DsyC/qHmdujqwrUa1WSspCsk= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.18.2 h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q= -sigs.k8s.io/controller-runtime v0.18.2/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= -sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= -sigs.k8s.io/structured-merge-diff v1.0.2 h1:WiMoyniAVAYm03w+ImfF9IE2G23GLR/SwDnQyaNZvPk= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= -vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc= diff --git a/hack/addheaders.sh b/hack/addheaders.sh deleted file mode 100755 index 4b30598c..00000000 --- a/hack/addheaders.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -version=v1.1.1 - -if ! hash addlicense 2>/dev/null; then - go install "github.com/google/addlicense@${version}" -fi - -# shellcheck disable=SC2035 -addlicense -f=hack/license-header.txt -ignore=test/samples/*.yaml -ignore=container-builder/examples/**/*.yaml api bundle cmd config container-builder env hack images internal log test utils workflowproj ./operator.yaml diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt index cb42c984..97867981 100644 --- a/hack/boilerplate.go.txt +++ b/hack/boilerplate.go.txt @@ -1,15 +1,15 @@ /* - * Copyright 2026 The Kubesmarts 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. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ \ No newline at end of file diff --git a/hack/bump-version.sh b/hack/bump-version.sh deleted file mode 100755 index ed17634b..00000000 --- a/hack/bump-version.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 - -# Source .env file if it exists -if [ -f .env ]; then - source .env -fi - -# Use environment variables with defaults -imageName="${REGISTRY:-quay.io}/${ACCOUNT:-kiegroup}/${OPERATOR_NAME:-logic-operator}" -imageTag="${IMAGE_TAG:-2.0.0}" -platformTag="${PLATFORM_TAG:-2.0.0}" -version="${VERSION:-2.0.0-snapshot}" - -if [ -z "${version}" ]; then - echo "Please inform the new version" - exit 1 -fi - -newMajorMinorVersion=${version%.*} - -targetSonataflowOperatorImage="${imageName}:${imageTag}" - -echo "Set new version to ${version} (majorMinor = ${newMajorMinorVersion}, imageName:imageTag = ${targetSonataflowOperatorImage})" - -# Note: Requires replace-in-file npm package installed globally: -# npm install -g replace-in-file - -node -p "require('replace-in-file').sync({ from: /\bnewTag:.*\b/g, to: 'newTag: ${version}', files: ['./config/manager/kustomization.yaml'] });" -node -p "require('replace-in-file').sync({ from: /\bnewName:.*\b/g, to: 'newName: ${imageName}', files: ['./config/manager/kustomization.yaml'] });" - -node -p "require('replace-in-file').sync({ from: /\bversion: .*\b/g, to: 'version: ${version}', files: ['./images/bundle.yaml'] });" -node -p "require('replace-in-file').sync({ from: /\bversion: .*\b/g, to: 'version: ${version}', files: ['./images/manager.yaml'] });" - -node -p "require('replace-in-file').sync({ from: /\boperatorVersion = .*/g, to: 'operatorVersion = \"${version}\"', files: ['api/version/version.go'] });" -node -p "require('replace-in-file').sync({ from: /\bplatformTagVersion = .*/g, to: 'platformTagVersion = \"${platformTag}\"', files: ['api/version/version.go'] });" - -echo "Version bumped to ${version}" diff --git a/hack/create-kind-cluster-with-registry.sh b/hack/create-kind-cluster-with-registry.sh deleted file mode 100755 index 03170e7c..00000000 --- a/hack/create-kind-cluster-with-registry.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/sh -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 -o errexit - -container_engine="$1" -reg_name='kind-registry' -reg_port='5001' - - -# 1. Create kind cluster with containerd registry config dir enabled -# TODO: kind will eventually enable this by default and this patch will -# be unnecessary. -# -# See: -# https://github.com/kubernetes-sigs/kind/issues/2875 -# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration -# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md -cat </dev/null || go install "golang.org/x/tools/cmd/goimports@${version}" -goimports -local github.com/apache -l -w . \ No newline at end of file diff --git a/hack/install-operator-sdk.sh b/hack/install-operator-sdk.sh deleted file mode 100755 index cd5a3b39..00000000 --- a/hack/install-operator-sdk.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 - -default_operator_sdk_version=v1.35.0 - -if [[ -z ${OPERATOR_SDK_VERSION} ]]; then - OPERATOR_SDK_VERSION=$default_operator_sdk_version -fi - -GOPATH=$(go env GOPATH) - -should_install=false -if [[ $(command -v operator-sdk) ]]; then - echo "---> operator-sdk is already installed. Checking the version." - operator_sdk_version=$(operator-sdk version | awk -F',' '{print $1}' | awk -F\" '{print $2}') - echo "---> operator-sdk installed version = ${operator_sdk_version}. Expected = ${OPERATOR_SDK_VERSION}" - if [ "${operator_sdk_version}" != "${OPERATOR_SDK_VERSION}" ]; then - echo "---> operator-sdk is not of the expected version. It will be re-installed." - should_install=true - fi -else - echo "---> operator-sdk not found. It will be installed." - should_install=true -fi - -if [ "${should_install}" = "true" ]; then - # get the arch and os - arch=$(uname -m) - case $(uname -m) in - "x86_64") arch="amd64"; ;; - "aarch64") arch="arm64"; ;; - esac - os=$(uname | awk '{print tolower($0)}') - echo "---> Installing operator-sdk (OS ${os} Architecture ${arch} in \$GOPATH/bin/" - mkdir -p "$GOPATH"/bin - - # Download with retry logic (GitHub can be flaky) - download_url="https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk_${os}_${arch}" - download_path="$GOPATH/bin/operator-sdk" - max_retries=3 - retry_count=0 - - while [ $retry_count -lt $max_retries ]; do - echo "---> Downloading from ${download_url} (attempt $((retry_count + 1))/${max_retries})" - if curl -sSL --fail --show-error "${download_url}" -o "${download_path}"; then - # Verify it's actually a binary (ELF for Linux, Mach-O for macOS) - if file "${download_path}" | grep -qE "ELF.*executable|Mach-O.*executable"; then - echo "---> Download successful" - chmod +x "${download_path}" - break - else - echo "---> Downloaded file is not a valid binary, retrying..." - rm -f "${download_path}" - fi - else - echo "---> Download failed, retrying..." - fi - retry_count=$((retry_count + 1)) - if [ $retry_count -lt $max_retries ]; then - sleep 2 - fi - done - - if [ $retry_count -eq $max_retries ]; then - echo "ERROR: Failed to download operator-sdk after ${max_retries} attempts" - exit 1 - fi -fi - -##For verification -operator_sdk_version=$(operator-sdk version | awk -F',' '{print $1}' | awk -F\" '{print $2}') -echo "---> Using operator-sdk version ${operator_sdk_version}" -if [ "${operator_sdk_version}" != "${OPERATOR_SDK_VERSION}" ]; then - echo "ERROR: After installation, operator-sdk is with version ${operator_sdk_version} but should be ${OPERATOR_SDK_VERSION}. Please check your PATH so that \$GOPATH/bin/ is prior." - exit 1 -fi \ No newline at end of file diff --git a/hack/license-header.txt b/hack/license-header.txt deleted file mode 100644 index 24a564df..00000000 --- a/hack/license-header.txt +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2026 The Kubesmarts 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. diff --git a/hack/local/run-e2e-crc.sh b/hack/local/run-e2e-crc.sh deleted file mode 100755 index c421f797..00000000 --- a/hack/local/run-e2e-crc.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# runs the e2e locally on crc -NAMESPACE=sonataflow-operator-system -oc registry login --insecure=true -docker login -u $(oc whoami) -p $(oc whoami -t) default-route-openshift-image-registry.apps-crc.testing -oc new-project "${NAMESPACE}" - -export OPERATOR_IMAGE_NAME=default-route-openshift-image-registry.apps-crc.testing/"${NAMESPACE}"/sonataflow-operator:latest -if ! make container-build BUILDER=docker IMG="${OPERATOR_IMAGE_NAME}"; then - echo "Failure: Failed to build image, exiting " >&2 - exit 1 -fi -make container-push BUILDER=docker IMG="${OPERATOR_IMAGE_NAME}" -make test-e2e diff --git a/hack/local/run-e2e.sh b/hack/local/run-e2e.sh deleted file mode 100755 index 94518613..00000000 --- a/hack/local/run-e2e.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# runs the e2e locally -# You must have minikube installed -MINIKUBE_PROFILE=${1:-minikube} -SKIP_IMG_BUILD=${2:-false} -TEST_LABELS=${3:-"flows-ephemeral"} # possible values are flows-ephemeral, flows-persistence, platform, cluster -SKIP_UNDEPLOY=${4:-false} - -# Emoticons and enhanced messages -echo "🚀 Using minikube profile ${MINIKUBE_PROFILE}" -export OPERATOR_IMAGE_NAME=localhost/kogito-serverless-operator:0.0.1 - -# Check if the minikube registry addon is enabled -if ! minikube addons list | grep -q "registry.*enabled"; then - echo "🔌 Enabling minikube registry addon..." - minikube addons enable registry -else - echo "✅ Minikube registry addon is already enabled." -fi - -# clean up previous runs, hiding logs -echo "🧹 Cleaning up previous test namespaces..." -kubectl get namespaces -o name | awk -F/ '/^namespace\/test/ {print $2}' | xargs kubectl delete namespace &> /dev/null - -if [ "${SKIP_UNDEPLOY}" = false ]; then - echo "🧹 Cleaning up previous test resources namespace..." - kubectl delete namespace e2e-resources &> /dev/null - echo "🧹 Undeploying previous instances..." - make undeploy ignore-not-found=true &> /dev/null -fi - -# Image build process -if [ "${SKIP_IMG_BUILD}" = "false" ]; then - # Check if cekit is available - if ! command -v cekit &> /dev/null; then - echo "❌ cekit command not found. Please install cekit before proceeding." >&2 - exit 1 - fi - echo "📦 Installing required Python packages for cekit..." - if ! pip install -r ./images/requirements.txt &> /dev/null; then - echo "❌ Failed to install required Python packages. Please check your requirements file." >&2 - exit 1 - fi - echo "🔨 Building operator image..." - eval "$(minikube -p "${MINIKUBE_PROFILE}" docker-env)" - if ! make container-build BUILDER=docker IMG="${OPERATOR_IMAGE_NAME}" ; then - echo "❌ Failure: Failed to build image, exiting." >&2 - exit 1 - fi -else - echo "⏩ Skipping operator image build..." -fi - -# Deploy and run tests, keeping logs visible for tests only -echo "🚀 Deploying operator..." -make deploy IMG="${OPERATOR_IMAGE_NAME}" &> /dev/null -echo "🧪 Running e2e tests with label ${TEST_LABELS}..." -make test-e2e label="${TEST_LABELS}" diff --git a/hack/local/run-operator.sh b/hack/local/run-operator.sh deleted file mode 100755 index 8b57477c..00000000 --- a/hack/local/run-operator.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Runs the operator locally via go main -POD_NAMESPACE=$(kubectl config view --minify | grep namespace | cut -d" " -f6) - -export POD_NAMESPACE - -kubectl delete --ignore-not-found=true -f ./bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml -kubectl delete --ignore-not-found=true -f ./bundle/manifests/sonataflow.org_sonataflowplatforms.yaml -kubectl delete --ignore-not-found=true -f ./bundle/manifests/sonataflow.org_sonataflowbuilds.yaml -kubectl delete --ignore-not-found=true -f ./bundle/manifests/sonataflow.org_sonataflows.yaml - -kubectl create -f ./bundle/manifests/sonataflow.org_sonataflowplatforms.yaml -kubectl create -f ./bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml -kubectl create -f ./bundle/manifests/sonataflow.org_sonataflowbuilds.yaml -kubectl create -f ./bundle/manifests/sonataflow.org_sonataflows.yaml -kubectl apply -f ./bundle/manifests/sonataflow-operator-builder-config_v1_configmap.yaml - -make debug \ No newline at end of file diff --git a/hack/pull-test-images.sh b/hack/pull-test-images.sh deleted file mode 100755 index 762fab8d..00000000 --- a/hack/pull-test-images.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# -# Copyright 2026 The Kubesmarts 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. - -set -e - -# Pull required images from quay.io/kubesmarts for e2e testing -echo "📥 Pulling Kubesmarts test images from quay.io..." - -# Source .env file if it exists to get image references -if [ -f .env ]; then - source .env -fi - -# Use environment variables or defaults -BUILDER_IMAGE=${RELATED_IMAGE_BASE_BUILDER:-quay.io/kubesmarts/incubator-kie-sonataflow-builder:main} -DEVMODE_IMAGE=${RELATED_IMAGE_DEVMODE:-quay.io/kubesmarts/incubator-kie-sonataflow-devmode:main} -DATA_INDEX_EPHEMERAL=${RELATED_IMAGE_DATA_INDEX_EPHEMERAL:-quay.io/kubesmarts/incubator-kie-kogito-data-index-ephemeral:main} -DATA_INDEX_POSTGRESQL=${RELATED_IMAGE_DATA_INDEX_POSTGRESQL:-quay.io/kubesmarts/incubator-kie-kogito-data-index-postgresql:main} -JOBS_SERVICE_EPHEMERAL=${RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL:-quay.io/kubesmarts/incubator-kie-kogito-jobs-service-ephemeral:main} -JOBS_SERVICE_POSTGRESQL=${RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL:-quay.io/kubesmarts/incubator-kie-kogito-jobs-service-postgresql:main} - -echo "🔄 Pulling builder image: ${BUILDER_IMAGE}" -docker pull "${BUILDER_IMAGE}" - -echo "🔄 Pulling devmode image: ${DEVMODE_IMAGE}" -docker pull "${DEVMODE_IMAGE}" - -echo "🔄 Pulling data-index (ephemeral): ${DATA_INDEX_EPHEMERAL}" -docker pull "${DATA_INDEX_EPHEMERAL}" - -echo "🔄 Pulling data-index (postgresql): ${DATA_INDEX_POSTGRESQL}" -docker pull "${DATA_INDEX_POSTGRESQL}" - -echo "🔄 Pulling jobs-service (ephemeral): ${JOBS_SERVICE_EPHEMERAL}" -docker pull "${JOBS_SERVICE_EPHEMERAL}" - -echo "🔄 Pulling jobs-service (postgresql): ${JOBS_SERVICE_POSTGRESQL}" -docker pull "${JOBS_SERVICE_POSTGRESQL}" - -echo "✅ All required images pulled successfully" diff --git a/hack/setup-cekit.sh b/hack/setup-cekit.sh deleted file mode 100755 index 46eb3642..00000000 --- a/hack/setup-cekit.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# -# Copyright 2026 The Kubesmarts 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. - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -VENV_DIR="$REPO_ROOT/venv" - -# Create virtual environment if it doesn't exist -if [ ! -d "$VENV_DIR" ]; then - echo "Creating Python virtual environment..." - python3 -m venv "$VENV_DIR" -fi - -# Activate virtual environment and install cekit -echo "Installing CEKit and dependencies..." -source "$VENV_DIR/bin/activate" -pip3 install -q -r "$REPO_ROOT/images/requirements.txt" - -echo "CEKit setup complete. Virtual environment at: $VENV_DIR" -echo "To use cekit, run: source venv/bin/activate" diff --git a/hack/update_patch_env.py b/hack/update_patch_env.py deleted file mode 100644 index 5d79dd3c..00000000 --- a/hack/update_patch_env.py +++ /dev/null @@ -1,119 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -from ruamel.yaml import YAML -import re -import sys -import subprocess - -PATCH_FILE = "config/manager/manager_env_patch.yaml" -BUILDER_DOCKERFILE = "config/manager/SonataFlow-Builder.containerfile" - -yaml = YAML() -yaml.preserve_quotes = True - -def resolve_digest(tool, image): - if not tool: - return image # no digest pinning if tool is empty - if tool not in ["docker", "podman", "skopeo"]: - raise ValueError(f"Unsupported tool for digest resolution: {tool}") - - try: - if tool == "docker": - inspect = subprocess.check_output([ - "docker", "buildx", "imagetools", "inspect", image - ], stderr=subprocess.DEVNULL, text=True) - match = re.search(r'sha256:[a-f0-9]+', inspect) - if match: - digest = match.group(0) - return f"{image.split('@')[0].split(':')[0]}@{digest}" - elif tool == "podman": - inspect = subprocess.check_output([ - "podman", "image", "inspect", "--format", "{{.Digest}}", image - ], stderr=subprocess.DEVNULL, text=True).strip() - if inspect.startswith("sha256"): - return f"{image.split('@')[0].split(':')[0]}@{inspect}" - elif tool == "skopeo": - inspect = subprocess.check_output([ - "skopeo", "inspect", f"docker://{image}" - ], stderr=subprocess.DEVNULL, text=True) - match = re.search(r'"Digest":\s*"(sha256:[a-f0-9]+)"', inspect) - if match: - digest = match.group(1) - return f"{image.split('@')[0].split(':')[0]}@{digest}" - - print(f"⚠️ Could not resolve digest for {image}, using as-is") - return image - except subprocess.CalledProcessError: - print(f"⚠️ Could not resolve digest for {image}, using as-is") - return image - -def update_kustomize_patch(env_var_mappings): - with open(PATCH_FILE, "r") as file: - data = yaml.load(file) - - containers = data.get("spec", {}).get("template", {}).get("spec", {}).get("containers", []) - for container in containers: - if container.get("name") == "manager": - env_list = container.setdefault("env", []) - for name, value in env_var_mappings.items(): - found = False - for env in env_list: - if env.get("name") == name: - env["value"] = value - found = True - break - if not found: - env_list.append({"name": name, "value": value}) - break - - with open(PATCH_FILE, "w") as file: - yaml.dump(data, file) - -def update_dockerfile(base_image_tag): - with open(BUILDER_DOCKERFILE, "r") as file: - dockerfile_lines = file.readlines() - - for i, line in enumerate(dockerfile_lines): - if line.strip().startswith("FROM"): - match = re.match(r"FROM\s+(\S+)(.*)", line.strip()) - if match: - trailing = match.group(2) - dockerfile_lines[i] = f"FROM {base_image_tag}{trailing}\n" - print(f"📋 Updated Dockerfile FROM clause to: {dockerfile_lines[i].strip()}") - break - - with open(BUILDER_DOCKERFILE, "w") as file: - file.writelines(dockerfile_lines) - -if __name__ == "__main__": - if len(sys.argv) < 2: - print("Usage: python update_patch_env.py ...") - sys.exit(1) - - tool = sys.argv[1] - mappings = sys.argv[2:] - - env_mappings = {} - for mapping in mappings: - k, v = mapping.split("=", 1) - env_mappings[k] = resolve_digest(tool, v) if k.startswith("RELATED_IMAGE_") else v - - update_kustomize_patch(env_mappings) - - if "RELATED_IMAGE_BASE_BUILDER" in env_mappings: - update_dockerfile(env_mappings["RELATED_IMAGE_BASE_BUILDER"]) diff --git a/images/bundle.yaml b/images/bundle.yaml deleted file mode 100644 index 301f2d06..00000000 --- a/images/bundle.yaml +++ /dev/null @@ -1,68 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -schema_version: 1 -name: "sonataflow-operator-bundle" -description: "SonataFlow Operator Bundle" -version: 0.0.0 -from: "scratch" - -args: - - name: SOURCE_DATE_EPOCH - description: Preserve timestamp while copying files - -labels: - - name: maintainer - value: dev@kie.apache.org - - name: io.k8s.description - value: Operator Bundle for deploying OpenShift Serverless Logic Operator - - name: io.k8s.display-name - value: SonataFlow Operator Bundle - - name: io.openshift.tags - value: sonataflow,serverless,workflow,operator - - name: operators.operatorframework.io.bundle.mediatype.v1 - value: registry+v1 - - name: operators.operatorframework.io.bundle.manifests.v1 - value: manifests/ - - name: operators.operatorframework.io.bundle.metadata.v1 - value: metadata/ - - name: operators.operatorframework.io.bundle.package.v1 - value: sonataflow-operator - - name: operators.operatorframework.io.bundle.channels.v1 - value: "stable" - - name: operators.operatorframework.io.bundle.channel.default.v1 - value: stable - - name: operators.operatorframework.io.metrics.mediatype.v1 - value: metrics+v1 - - name: operators.operatorframework.io.metrics.builder - value: operator-sdk-v1.35.0 - - name: operators.operatorframework.io.metrics.project_layout - value: go.kubebuilder.io/v3 - - name: operators.operatorframework.io.test.config.v1 - value: tests/scorecard/ - - name: operators.operatorframework.io.test.mediatype.v1 - value: scorecard+v1 - - name: com.redhat.delivery.operator.bundle - value: "true" - - name: com.redhat.openshift.versions - value: v4.11 - -modules: - repositories: - - path: modules - install: - - name: org.apache.kie.sonataflow.bundle diff --git a/images/manager.yaml b/images/manager.yaml deleted file mode 100644 index 65622f72..00000000 --- a/images/manager.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: operator-builder - version: 0.0.0 - from: "golang:1.26" - description: Builder Image for the Operator - - args: - - name: SOURCE_DATE_EPOCH - value: - - modules: - repositories: - - path: modules - install: - - name: org.apache.kie.sonataflow.goModDownload - - name: org.apache.kie.sonataflow.operatorBuilder - -- name: sonataflow-operator - version: 0.0.0 - from: "registry.access.redhat.com/ubi9/ubi-micro:9.5" - description: Runtime Image for the Operator - - args: - - name: SOURCE_DATE_EPOCH - value: - - labels: - - name: maintainer - value: dev@kie.apache.org - - artifacts: - - path: /workspace/manager - image: operator-builder - dest: /usr/local/bin - name: manager - - run: - workdir: /usr/local/bin - user: "65532:65532" - entrypoint: - - manager diff --git a/images/modules/org.apache.kie.sonataflow.bundle/module.yaml b/images/modules/org.apache.kie.sonataflow.bundle/module.yaml deleted file mode 100644 index a5ddd386..00000000 --- a/images/modules/org.apache.kie.sonataflow.bundle/module.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: org.apache.kie.sonataflow.bundle -version: "main" -description: Copy the bundle files to the target image - -artifacts: - - name: manifests - path: "../../../../bundle/manifests" - dest: /manifests/ - - name: metadata - path: "../../../../bundle/metadata" - dest: /metadata/ - - name: tests-scorecard - path: "../../../../bundle/tests/scorecard/" - dest: /tests/scorecard/ diff --git a/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh b/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh deleted file mode 100755 index e2d36e4f..00000000 --- a/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 -cd /workspace -go mod download \ No newline at end of file diff --git a/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml b/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml deleted file mode 100644 index fa19a683..00000000 --- a/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: org.apache.kie.sonataflow.goModDownload -version: "main" -description: Download and cache the modules -artifacts: - - name: gomod - path: "../../../../go.mod" - target: "go.mod" - dest: /workspace/ - - - name: gosum - path: "../../../../go.sum" - target: "go.sum" - dest: /workspace/ - - # this is a local module, adding in here since the main go.mod refers to it - - name: api - path: "../../../../api" - dest: /workspace/api - - # this is a local module, adding in here since the main go.mod refers to it - - name: workflowproj - path: "../../../../workflowproj" - dest: /workspace/workflowproj - - # this is a local module, adding in here since the main go.mod refers to it - - name: container-builder - path: "../../../../container-builder" - dest: /workspace/container-builder - -execute: - - script: install.sh diff --git a/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh b/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh deleted file mode 100644 index fac64ed1..00000000 --- a/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 - -cd /workspace -CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags=-buildid= -a -o manager cmd/main.go; \ No newline at end of file diff --git a/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml b/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml deleted file mode 100644 index 3a0c8751..00000000 --- a/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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: org.apache.kie.sonataflow.operatorBuilder -version: "main" -description: Builds the operator binary - -artifacts: - - name: main - path: "../../../../cmd/main.go" - target: "main.go" - dest: /workspace/cmd - - - name: controllers - path: "../../../../internal/controller" - dest: /workspace/internal/controller - - - name: manager - path: "../../../../internal/manager" - dest: /workspace/internal/manager - - - name: utils - path: "../../../../utils" - dest: /workspace/utils - - - name: log - path: "../../../../log" - dest: /workspace/log - -execute: - - script: install.sh diff --git a/images/requirements.txt b/images/requirements.txt deleted file mode 100644 index 37f00565..00000000 --- a/images/requirements.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Requirements for cekit 4.11.0 build -# see: https://pip.pypa.io/en/stable/reference/requirements-file-format/ - -requests<2.32.0 -cekit==4.16.0 -behave==1.2.6 -lxml==5.2.1 -docker==7.1.0 -docker-squash==1.2.2 -python-docker -elementpath==4.4.0 -pyyaml==6.0.1 -ruamel.yaml==0.18.6 -python-dateutil==2.9.0.post0 -Jinja2==3.1.6 -pykwalify==1.8.0 -colorlog==6.8.2 -click==8.1.7 -odcs -behave -krb5 diff --git a/internal/controller/builder/builder.go b/internal/controller/builder/builder.go deleted file mode 100644 index 7821e0d6..00000000 --- a/internal/controller/builder/builder.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - - "k8s.io/klog/v2" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/log" -) - -type buildManagerContext struct { - ctx context.Context - client client.Client - platform *operatorapi.SonataFlowPlatform - builderConfigMap *v1.ConfigMap -} - -type BuildManager interface { - Schedule(build *operatorapi.SonataFlowBuild) error - Reconcile(build *operatorapi.SonataFlowBuild) error -} - -func NewBuildManager(ctx context.Context, client client.Client, cliConfig *rest.Config, targetName, targetNamespace string) (BuildManager, error) { - p, err := platform.GetActivePlatform(ctx, client, targetNamespace, true) - if err != nil { - if errors.IsNotFound(err) { - return nil, err - } - klog.V(log.E).ErrorS(err, "Error retrieving the active platform. Workflow build cannot be performed!", "workflow", targetName) - return nil, err - } - builderConfig, err := GetBuilderConfigMap(client, targetNamespace) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to get common configMap for Workflow Builder. Make sure that sonataflow-operator-builder-config is present in the operator namespace.") - return nil, err - } - managerContext := buildManagerContext{ - ctx: ctx, - client: client, - platform: p, - builderConfigMap: builderConfig, - } - switch p.Status.Cluster { - case operatorapi.PlatformClusterOpenShift: - return newOpenShiftBuilderManager(managerContext, cliConfig) - case operatorapi.PlatformClusterKubernetes: - return newContainerBuilderManager(managerContext, cliConfig), nil - default: - klog.V(log.I).InfoS("Impossible to check the Cluster type in the SonataFlowPlatform") - return newContainerBuilderManager(managerContext, cliConfig), nil - } -} - -// fetchWorkflowForBuild fetches the k8s API for the workflow from the given build -func (b *buildManagerContext) fetchWorkflowForBuild(build *operatorapi.SonataFlowBuild) (workflow *operatorapi.SonataFlow, err error) { - workflow = &operatorapi.SonataFlow{} - if err = b.client.Get(b.ctx, client.ObjectKeyFromObject(build), workflow); err != nil { - return nil, err - } - return -} diff --git a/internal/controller/builder/config.go b/internal/controller/builder/config.go deleted file mode 100644 index 882576f5..00000000 --- a/internal/controller/builder/config.go +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - "fmt" - "os" - - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - "github.com/kubesmarts/logic-operator/log" -) - -const ( - envVarPodNamespaceName = "POD_NAMESPACE" - configKeyDefaultExtension = "DEFAULT_WORKFLOW_EXTENSION" - defaultBuilderResourceName = "Dockerfile" -) - -// GetBuilderConfigMap retrieves the config map with the builder common configuration information -func GetBuilderConfigMap(client client.Client, fallbackNS string) (*corev1.ConfigMap, error) { - namespace, found := os.LookupEnv(envVarPodNamespaceName) - if !found { - namespace = fallbackNS - } - - if !found && len(namespace) == 0 { - return nil, errors.Errorf("Can't find current context namespace, make sure that %s env is set", envVarPodNamespaceName) - } - - existingConfigMap := &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: cfg.GetCfg().BuilderConfigMapName, - Namespace: namespace, - }, - Data: map[string]string{}, - } - - builderConfigMapName := cfg.GetCfg().BuilderConfigMapName - err := client.Get(context.TODO(), types.NamespacedName{Name: builderConfigMapName, Namespace: namespace}, existingConfigMap) - if err != nil { - klog.V(log.E).ErrorS(err, "fetching configmap", "name", builderConfigMapName) - return nil, err - } - - err = isValidBuilderConfigMap(existingConfigMap) - if err != nil { - klog.V(log.E).ErrorS(err, "configmap is not valid", "name", builderConfigMapName) - return existingConfigMap, err - } - - return existingConfigMap, nil -} - -// isValidBuilderConfigMap function that will verify that in the builder config maps there are the required keys, and they aren't empty -func isValidBuilderConfigMap(configMap *corev1.ConfigMap) error { - // Verifying that the key to hold the extension for the workflow is there and not empty - if len(configMap.Data[configKeyDefaultExtension]) == 0 { - return fmt.Errorf("unable to find %s key into builder config map", configMap.Data[configKeyDefaultExtension]) - } - - // Verifying that the key to hold the content of the Dockerfile for building the workflow is there and not empty - if len(configMap.Data[defaultBuilderResourceName]) == 0 { - return fmt.Errorf("unable to find %s key into builder config map", configMap.Data[defaultBuilderResourceName]) - } - return nil -} diff --git a/internal/controller/builder/containerbuilder.go b/internal/controller/builder/containerbuilder.go deleted file mode 100644 index cd0bd16b..00000000 --- a/internal/controller/builder/containerbuilder.go +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "time" - - "github.com/kubesmarts/logic-operator/workflowproj" - - corev1 "k8s.io/api/core/v1" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - clientr "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/utils" - - "github.com/kubesmarts/logic-operator/container-builder/api" - builder "github.com/kubesmarts/logic-operator/container-builder/builder/kubernetes" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/log" -) - -const ( - resourceDockerfile = "Dockerfile" -) - -var _ BuildManager = &containerBuilderManager{} - -type kanikoBuildInput struct { - name string - task *api.KanikoTask - workflowDefinition []byte - workflow *operatorapi.SonataFlow - workflowProperties []operatorapi.ConfigMapWorkflowResource - dockerfile string - imageTag string -} - -type containerBuilderManager struct { - buildManagerContext - // needed for the internal container-builder - restConfig *rest.Config -} - -func (c *containerBuilderManager) Schedule(build *operatorapi.SonataFlowBuild) error { - kanikoTaskCache := api.KanikoTaskCache{} - if platform.IsKanikoCacheEnabled(c.platform) { - kanikoTaskCache.Enabled = utils.Pbool(true) - } - kanikoTask := &api.KanikoTask{ - ContainerBuildBaseTask: api.ContainerBuildBaseTask{ - Name: "kaniko", - BuildArgs: build.Spec.BuildArgs, - Envs: build.Spec.Envs, - Resources: build.Spec.Resources, - }, - PublishTask: api.PublishTask{}, - Cache: kanikoTaskCache, - AdditionalFlags: build.Spec.Arguments, - KanikoExecutorImage: cfg.GetCfg().KanikoExecutorImageTag, - } - var containerBuilder *api.ContainerBuild - var err error - if containerBuilder, err = c.scheduleNewKanikoBuildWithContainerFile(build, kanikoTask); err != nil { - return err - } - if containerBuilder == nil { - return nil - } - if err = build.Status.SetInnerBuild(containerBuilder); err != nil { - return err - } - build.Status.BuildPhase = operatorapi.BuildPhase(containerBuilder.Status.Phase) - if len(build.Status.BuildPhase) == 0 { - build.Status.BuildPhase = operatorapi.BuildPhaseInitialization - } - build.Status.Error = containerBuilder.Status.Error - return nil -} - -func (c *containerBuilderManager) Reconcile(build *operatorapi.SonataFlowBuild) error { - containerBuild := &api.ContainerBuild{} - if err := build.Status.GetInnerBuild(containerBuild); err != nil { - return err - } - containerCli, _ := clientr.FromCtrlClientSchemeAndConfig(c.client, c.client.Scheme(), c.restConfig) - containerBuild, err := c.reconcileBuild(containerBuild, containerCli) - if err != nil { - return err - } - build.Status.BuildPhase = operatorapi.BuildPhase(containerBuild.Status.Phase) - build.Status.Error = containerBuild.Status.Error - build.Status.ImageTag = containerBuild.Status.RepositoryImageTag - if err = build.Status.SetInnerBuild(containerBuild); err != nil { - return err - } - return nil -} - -func newContainerBuilderManager(managerContext buildManagerContext, config *rest.Config) BuildManager { - return &containerBuilderManager{ - buildManagerContext: managerContext, - restConfig: config, - } -} - -func (c *containerBuilderManager) scheduleNewKanikoBuildWithContainerFile(build *operatorapi.SonataFlowBuild, task *api.KanikoTask) (*api.ContainerBuild, error) { - workflow, err := c.fetchWorkflowForBuild(build) - if err != nil { - return nil, err - } - workflowDef, err := workflowdef.GetJSONWorkflow(workflow, c.ctx) - if err != nil { - return nil, err - } - - buildInput := kanikoBuildInput{ - name: workflow.Name, - task: task, - workflowDefinition: workflowDef, - workflow: workflow, - workflowProperties: buildWorkflowPropertyResources(workflow), - dockerfile: platform.GetCustomizedBuilderDockerfile(c.builderConfigMap.Data[defaultBuilderResourceName], *c.platform), - imageTag: buildNamespacedImageTag(workflow), - } - - if c.platform.Spec.Build.Config.Timeout == nil { - c.platform.Spec.Build.Config.Timeout = &metav1.Duration{Duration: 5 * time.Minute} - } - return c.buildImage(buildInput) -} - -func (c *containerBuilderManager) reconcileBuild(build *api.ContainerBuild, cli client.Client) (*api.ContainerBuild, error) { - result, err := builder.FromBuild(build).WithClient(cli).Reconcile() - return result, err -} - -func (c *containerBuilderManager) buildImage(buildInput kanikoBuildInput) (*api.ContainerBuild, error) { - cli, err := client.FromCtrlClientSchemeAndConfig(c.client, c.client.Scheme(), c.restConfig) - plat := api.PlatformContainerBuild{ - ObjectReference: api.ObjectReference{ - Namespace: c.platform.Namespace, - Name: buildInput.name, - }, - Spec: api.PlatformContainerBuildSpec{ - BuildStrategy: api.ContainerBuildStrategyPod, - PublishStrategy: api.PlatformBuildPublishStrategyKaniko, - Registry: api.ContainerRegistrySpec{ - Insecure: c.platform.Spec.Build.Config.Registry.Insecure, - Address: c.platform.Spec.Build.Config.Registry.Address, - Secret: c.platform.Spec.Build.Config.Registry.Secret, - }, - Timeout: &metav1.Duration{ - Duration: c.platform.Spec.Build.Config.Timeout.Duration, - }, - }, - } - - build, err := newBuild(buildInput, plat, c.builderConfigMap.Data[configKeyDefaultExtension], cli) - if err != nil { - klog.V(log.E).ErrorS(err, "error during build Image") - return nil, err - } - return build, err -} - -// Helper function to create a new container-builder build and schedule it -func newBuild(buildInput kanikoBuildInput, platform api.PlatformContainerBuild, defaultExtension string, cli client.Client) (*api.ContainerBuild, error) { - buildInfo := builder.ContainerBuilderInfo{ - FinalImageName: buildInput.imageTag, - BuildUniqueName: buildInput.name, - Platform: platform, - ContainerBuilderImageTag: buildInput.task.KanikoExecutorImage, - } - - newBuilder := builder.NewBuild(buildInfo). - WithClient(cli). - AddResource(resourceDockerfile, []byte(buildInput.dockerfile)). - AddResource(buildInput.name+defaultExtension, buildInput.workflowDefinition) - for _, res := range buildInput.workflow.Spec.Resources.ConfigMaps { - newBuilder.AddConfigMapResource(res.ConfigMap, res.WorkflowPath) - } - - //make the workflow properties available to the kaniko build. - for _, props := range buildInput.workflowProperties { - newBuilder.AddConfigMapResource(props.ConfigMap, props.WorkflowPath) - } - - return newBuilder.Scheduler(). - WithAdditionalArgs(buildInput.task.AdditionalFlags). - WithResourceRequirements(buildInput.task.Resources). - WithBuildArgs(buildInput.task.BuildArgs). - WithEnvs(buildInput.task.Envs).Schedule() -} - -// buildNamespacedImageTag For the kaniko build we prepend the namespace to the calculated image name/tag to avoid potential -// collisions if the same workflows is deployed in a different namespace. In OpenShift this last is not needed since the -// ImageStreams are already namespaced. -func buildNamespacedImageTag(workflow *operatorapi.SonataFlow) string { - return workflow.Namespace + "/" + workflowdef.GetWorkflowAppImageNameTag(workflow) -} - -func buildWorkflowPropertyResources(workflow *operatorapi.SonataFlow) []operatorapi.ConfigMapWorkflowResource { - return []operatorapi.ConfigMapWorkflowResource{ - {ConfigMap: corev1.LocalObjectReference{Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow)}, WorkflowPath: ""}, - {ConfigMap: corev1.LocalObjectReference{Name: workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow)}, WorkflowPath: ""}, - } -} diff --git a/internal/controller/builder/kogitoserverlessbuild_manager.go b/internal/controller/builder/kogitoserverlessbuild_manager.go deleted file mode 100644 index 7ba7f9e1..00000000 --- a/internal/controller/builder/kogitoserverlessbuild_manager.go +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - "strings" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - - "github.com/kubesmarts/logic-operator/internal/controller/platform" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const QuarkusExtensionsBuildArg = "QUARKUS_EXTENSIONS" - -var _ SonataFlowBuildManager = &sonataFlowBuildManager{} - -type sonataFlowBuildManager struct { - client client.Client - ctx context.Context -} - -func (k *sonataFlowBuildManager) MarkToRestart(build *operatorapi.SonataFlowBuild) error { - build.Status.BuildPhase = operatorapi.BuildPhaseNone - return k.client.Status().Update(k.ctx, build) -} - -func (k *sonataFlowBuildManager) GetOrCreateBuild(workflow *operatorapi.SonataFlow) (*operatorapi.SonataFlowBuild, error) { - buildInstance := &operatorapi.SonataFlowBuild{} - buildInstance.ObjectMeta.Namespace = workflow.Namespace - buildInstance.ObjectMeta.Name = workflow.Name - - if err := k.client.Get(k.ctx, client.ObjectKeyFromObject(workflow), buildInstance); err != nil { - if errors.IsNotFound(err) { - plat := &operatorapi.SonataFlowPlatform{} - if plat, err = platform.GetActivePlatform(k.ctx, k.client, workflow.Namespace, true); err != nil { - return nil, err - } - workflowBuildTemplate := plat.Spec.Build.Template.DeepCopy() - if persistence.UsesPostgreSQLPersistence(workflow, plat) { - addPersistenceExtensions(workflowBuildTemplate) - } - buildInstance.Spec.BuildTemplate = *workflowBuildTemplate - if err = controllerutil.SetControllerReference(workflow, buildInstance, k.client.Scheme()); err != nil { - return nil, err - } - if err = k.client.Create(k.ctx, buildInstance); err != nil { - return nil, err - } - return buildInstance, nil - } - return nil, err - } - - return buildInstance, nil -} - -type SonataFlowBuildManager interface { - // GetOrCreateBuild gets or creates a new instance of SonataFlowBuild for the given SonataFlow. - // - // Only one build is allowed per workflow instance. - GetOrCreateBuild(workflow *operatorapi.SonataFlow) (*operatorapi.SonataFlowBuild, error) - // MarkToRestart tell the controller to restart this build in the next iteration - MarkToRestart(build *operatorapi.SonataFlowBuild) error -} - -// NewSonataFlowBuildManager entry point to manage SonataFlowBuild instances. -// Won't start a build, but once it creates a new instance, the controller will take place and start the build in the cluster context. -func NewSonataFlowBuildManager(ctx context.Context, client client.Client) SonataFlowBuildManager { - return &sonataFlowBuildManager{ - client: client, - ctx: ctx, - } -} - -// addPersistenceExtensions Adds the persistence related extensions to the current BuildTemplate if none of them is -// already provided. If any of them is detected, its assumed that users might already have provided them in the -// SonataFlowPlatform, so we just let the provided configuration. -func addPersistenceExtensions(template *operatorapi.BuildTemplate) { - quarkusExtensions := getBuildArg(template.BuildArgs, QuarkusExtensionsBuildArg) - if quarkusExtensions == nil { - template.BuildArgs = append(template.BuildArgs, v1.EnvVar{Name: QuarkusExtensionsBuildArg}) - quarkusExtensions = &template.BuildArgs[len(template.BuildArgs)-1] - } - if !hasAnyExtensionPresent(quarkusExtensions, persistence.GetPostgreSQLExtensions()) { - for _, extension := range persistence.GetPostgreSQLExtensions() { - if len(quarkusExtensions.Value) > 0 { - quarkusExtensions.Value = quarkusExtensions.Value + "," - } - quarkusExtensions.Value = quarkusExtensions.Value + extension.String() - } - } -} - -func getBuildArg(buildArgs []v1.EnvVar, name string) *v1.EnvVar { - for i := 0; i < len(buildArgs); i++ { - if buildArgs[i].Name == name { - return &buildArgs[i] - } - } - return nil -} - -func hasAnyExtensionPresent(buildArg *v1.EnvVar, extensions []cfg.GroupArtifactId) bool { - for _, extension := range extensions { - if isExtensionPresent(buildArg, extension) { - return true - } - } - return false -} - -func isExtensionPresent(buildArg *v1.EnvVar, extension cfg.GroupArtifactId) bool { - return strings.Contains(buildArg.Value, extension.String()) -} diff --git a/internal/controller/builder/kogitoserverlessbuild_manager_test.go b/internal/controller/builder/kogitoserverlessbuild_manager_test.go deleted file mode 100644 index 20d55c6f..00000000 --- a/internal/controller/builder/kogitoserverlessbuild_manager_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 builder - -import ( - "testing" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - "github.com/kubesmarts/logic-operator/test" -) - -func TestSonataFlowBuildManager_GetOrCreateBuildWithWorkflowPersistence(t *testing.T) { - // Current platform with no persistence - currentPlatform := operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: "current-platform"}, - Spec: operatorapi.SonataFlowPlatformSpec{}, - Status: operatorapi.SonataFlowPlatformStatus{}, - } - // Persistence is configured in the workflow - workflow := operatorapi.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-workflow", - }, - Spec: operatorapi.SonataFlowSpec{ - Persistence: &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{}, - }, - }, - Status: operatorapi.SonataFlowStatus{}, - } - testGetOrCreateBuildWithPersistence(t, ¤tPlatform, &workflow) -} - -func TestSonataFlowBuildManager_GetOrCreateBuildWithPlatformPersistence(t *testing.T) { - // Persistence is configured in the platform - currentPlatform := operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: "current-platform"}, - Spec: operatorapi.SonataFlowPlatformSpec{ - Persistence: &operatorapi.PlatformPersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PlatformPersistencePostgreSQL{}, - }, - }, - Status: operatorapi.SonataFlowPlatformStatus{}, - } - // Workflow with no persistence - workflow := operatorapi.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-workflow", - }, - Status: operatorapi.SonataFlowStatus{}, - } - testGetOrCreateBuildWithPersistence(t, ¤tPlatform, &workflow) -} - -func TestSonataFlowBuildManager_GetOrCreateBuildWithNoPersistence(t *testing.T) { - // Platform has no persistence - currentPlatform := operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: "current-platform"}, - Spec: operatorapi.SonataFlowPlatformSpec{}, - Status: operatorapi.SonataFlowPlatformStatus{}, - } - // Workflow has no persistence - workflow := operatorapi.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-workflow", - }, - Status: operatorapi.SonataFlowStatus{}, - } - buildManager := prepareGetOrCreateBuildTest(t, ¤tPlatform) - build, _ := buildManager.GetOrCreateBuild(&workflow) - assert.Equal(t, 0, len(build.Spec.BuildArgs)) - test.RestoreControllersConfig(t) -} - -func testGetOrCreateBuildWithPersistence(t *testing.T, currentPlatform *operatorapi.SonataFlowPlatform, workflow *operatorapi.SonataFlow) { - buildManager := prepareGetOrCreateBuildTest(t, currentPlatform) - build, _ := buildManager.GetOrCreateBuild(workflow) - assert.NotNil(t, build) - assert.Equal(t, 1, len(build.Spec.BuildArgs)) - assertContainsPersistence(t, build.Spec.BuildArgs, 0) - test.RestoreControllersConfig(t) -} - -func prepareGetOrCreateBuildTest(t *testing.T, currentPlatform *operatorapi.SonataFlowPlatform) sonataFlowBuildManager { - initializeControllersConfig(t) - platforms := operatorapi.NewSonataFlowPlatformList() - platforms.Items = []operatorapi.SonataFlowPlatform{*currentPlatform} - cli := test.NewSonataFlowClientBuilder().WithRuntimeObjects(&platforms).Build() - buildManager := sonataFlowBuildManager{ - client: cli, - } - return buildManager -} - -func Test_addPersistenceExtensionsWithEmptyArgs(t *testing.T) { - initializeControllersConfig(t) - buildTemplate := &operatorapi.BuildTemplate{} - addPersistenceExtensions(buildTemplate) - assert.Equal(t, 1, len(buildTemplate.BuildArgs)) - assertContainsPersistence(t, buildTemplate.BuildArgs, 0) - test.RestoreControllersConfig(t) -} - -func Test_addPersistenceExtensionsWithNoQuarkusExtensionsArg(t *testing.T) { - initializeControllersConfig(t) - buildTemplate := &operatorapi.BuildTemplate{ - BuildArgs: []v1.EnvVar{ - {Name: "VAR1"}, - }, - } - addPersistenceExtensions(buildTemplate) - assert.Equal(t, 2, len(buildTemplate.BuildArgs)) - assertContainsPersistence(t, buildTemplate.BuildArgs, 1) - test.RestoreControllersConfig(t) -} - -func Test_addPersistenceExtensionsWithQuarkusExtensionsArgAndNoPersistenceExtensions(t *testing.T) { - initializeControllersConfig(t) - buildTemplate := &operatorapi.BuildTemplate{ - BuildArgs: []v1.EnvVar{ - {Name: "VAR1"}, - {Name: "QUARKUS_EXTENSIONS", Value: "org.acme:org.acme.library:1.0.0"}, - }, - } - addPersistenceExtensions(buildTemplate) - assert.Equal(t, 2, len(buildTemplate.BuildArgs)) - assertContainsPersistence(t, buildTemplate.BuildArgs, 1) - test.RestoreControllersConfig(t) -} - -func Test_addPersistenceExtensionsWithQuarkusExtensionsArgAndPersistenceExtensions(t *testing.T) { - initializeControllersConfig(t) - buildTemplate := &operatorapi.BuildTemplate{ - BuildArgs: []v1.EnvVar{ - {Name: "VAR1", Value: "VALUE1"}, - {Name: "QUARKUS_EXTENSIONS", Value: "org.acme:org.acme.library:1.0.0,io.quarkus:quarkus-jdbc-postgresql:8.8.0.Final"}, - }, - } - addPersistenceExtensions(buildTemplate) - assert.Equal(t, 2, len(buildTemplate.BuildArgs)) - assert.Equal(t, v1.EnvVar{Name: "VAR1", Value: "VALUE1"}, buildTemplate.BuildArgs[0]) - assert.Equal(t, v1.EnvVar{Name: "QUARKUS_EXTENSIONS", Value: "org.acme:org.acme.library:1.0.0,io.quarkus:quarkus-jdbc-postgresql:8.8.0.Final"}, buildTemplate.BuildArgs[1]) - test.RestoreControllersConfig(t) -} - -func initializeControllersConfig(t *testing.T) { - // emulate the controllers config initialization - cfg, err := cfg.InitializeControllersCfgAt("../cfg/testdata/controllers-cfg-test.yaml") - assert.NoError(t, err) - assert.NotNil(t, cfg) - assert.Equal(t, 3, len(cfg.PostgreSQLPersistenceExtensions)) -} - -func assertContainsPersistence(t *testing.T, buildArgs []v1.EnvVar, position int) { - assert.GreaterOrEqual(t, len(buildArgs), position) - envVar := buildArgs[position] - assert.Equal(t, QuarkusExtensionsBuildArg, envVar.Name) - for _, extension := range persistence.GetPostgreSQLExtensions() { - assert.Contains(t, envVar.Value, extension.String()) - } -} diff --git a/internal/controller/builder/openshiftbuilder.go b/internal/controller/builder/openshiftbuilder.go deleted file mode 100644 index 5576680f..00000000 --- a/internal/controller/builder/openshiftbuilder.go +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - "strings" - - "github.com/kubesmarts/logic-operator/internal/controller/openshift" - - buildv1 "github.com/openshift/api/build/v1" - imgv1 "github.com/openshift/api/image/v1" - buildclientv1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/workflowproj" - - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - "github.com/kubesmarts/logic-operator/utils" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const ( - imageStreamTagKind = "ImageStreamTag" - defaultBuildMessageTrigger = "Triggered by SonataFlow Operator" -) - -// openshiftBuildPhaseMatrix Build phases correlations: -// -// - BuildPhaseScheduling: When we first schedule the build to the OpenShift cluster by creating a new BuildConfig for the workflow. -// There's no Build instance at this point, if there's, it's in "New" phase. -// - BuildPhasePending: When we fetch the Build, and we mimic its status, meaning that a pod has been scheduled to start the build. -// - BuildPhaseRunning: -- -// - BuildPhaseSucceeded: "Complete" for the OCP Build -// - BuildPhaseFailed: -- -// - BuildPhaseError: -- -// - BuildPhaseInterrupted: "Cancelled" for the OCP Build -var openshiftBuildPhaseMatrix = map[buildv1.BuildPhase]operatorapi.BuildPhase{ - buildv1.BuildPhaseNew: operatorapi.BuildPhaseScheduling, - buildv1.BuildPhasePending: operatorapi.BuildPhasePending, - buildv1.BuildPhaseRunning: operatorapi.BuildPhaseRunning, - buildv1.BuildPhaseComplete: operatorapi.BuildPhaseSucceeded, - buildv1.BuildPhaseFailed: operatorapi.BuildPhaseFailed, - buildv1.BuildPhaseError: operatorapi.BuildPhaseError, - buildv1.BuildPhaseCancelled: operatorapi.BuildPhaseInterrupted, -} - -var _ BuildManager = &openshiftBuilderManager{} - -type openshiftBuilderManager struct { - buildManagerContext - buildClient buildclientv1.BuildV1Interface -} - -func newOpenShiftBuilderManager(managerContext buildManagerContext, cliConfig *rest.Config) (BuildManager, error) { - buildClient, err := openshift.NewOpenShiftBuildClient(cliConfig) - if err != nil { - return nil, err - } - return newOpenShiftBuilderManagerWithClient(managerContext, buildClient), err -} - -// Used internally for testing purposes, but in the future could be used by the main factory. -// There's no special code related to testing, but we do expose an interface to inject the internal build client. -func newOpenShiftBuilderManagerWithClient(managerContext buildManagerContext, buildClient buildclientv1.BuildV1Interface) BuildManager { - manager := &openshiftBuilderManager{ - buildManagerContext: managerContext, - } - manager.buildClient = buildClient - return manager -} - -func (o *openshiftBuilderManager) Schedule(build *operatorapi.SonataFlowBuild) error { - is := &imgv1.ImageStream{ - ObjectMeta: metav1.ObjectMeta{ - Name: build.Name, - Namespace: build.Namespace, - }, - Spec: imgv1.ImageStreamSpec{ - LookupPolicy: imgv1.ImageLookupPolicy{ - Local: true, - }, - }, - } - workflow, err := o.fetchWorkflowForBuild(build) - if err != nil { - return err - } - bc := o.newDefaultBuildConfig(build, workflow) - if err = o.addExternalResources(bc, workflow); err != nil { - return err - } - workflowproj.SetMergedLabels(workflow, is) - workflowproj.SetMergedLabels(workflow, bc) - if err = controllerutil.SetControllerReference(build, bc, o.buildManagerContext.client.Scheme()); err != nil { - return err - } - if err = controllerutil.SetControllerReference(build, is, o.buildManagerContext.client.Scheme()); err != nil { - return err - } - - // Persist our objects - if _, err = controllerutil.CreateOrPatch(o.ctx, o.client, is, func() error { - is.Spec.LookupPolicy.Local = true - return nil - }); err != nil { - return err - } - if _, err = controllerutil.CreateOrPatch(o.ctx, o.client, bc, func() error { - if kubeutil.IsObjectNew(bc) { - return nil - } - referenceBC := o.newDefaultBuildConfig(build, workflow) - bc.Spec = *referenceBC.Spec.DeepCopy() - return o.addExternalResources(bc, workflow) - }); err != nil { - return err - } - - build.Status.BuildPhase = operatorapi.BuildPhaseInitialization - return nil -} - -func (o *openshiftBuilderManager) newDefaultBuildConfig(build *operatorapi.SonataFlowBuild, workflow *operatorapi.SonataFlow) *buildv1.BuildConfig { - optimizationPol := buildv1.ImageOptimizationSkipLayers - dockerFile := platform.GetCustomizedBuilderDockerfile(o.builderConfigMap.Data[defaultBuilderResourceName], *o.platform) - forcePull := kubeutil.GetImageTag(platform.GetFromImageTagDockerfile(dockerFile)) == "latest" - return &buildv1.BuildConfig{ - ObjectMeta: metav1.ObjectMeta{Namespace: build.Namespace, Name: build.Name}, - Spec: buildv1.BuildConfigSpec{ - RunPolicy: buildv1.BuildRunPolicySerial, - FailedBuildsHistoryLimit: utils.Pint(1), - SuccessfulBuildsHistoryLimit: utils.Pint(3), - CommonSpec: buildv1.CommonSpec{ - Source: buildv1.BuildSource{ - Type: buildv1.BuildSourceBinary, - Dockerfile: &dockerFile, - }, - Strategy: buildv1.BuildStrategy{ - Type: buildv1.DockerBuildStrategyType, - DockerStrategy: &buildv1.DockerBuildStrategy{ - ImageOptimizationPolicy: &optimizationPol, - BuildArgs: build.Spec.BuildArgs, - Env: build.Spec.Envs, - ForcePull: forcePull, - }, - }, - Output: buildv1.BuildOutput{ - To: &corev1.ObjectReference{ - Namespace: build.Namespace, - Name: workflowdef.GetWorkflowAppImageNameTag(workflow), - Kind: imageStreamTagKind, - }, - }, - Resources: build.Spec.Resources, - }, - }, - } -} - -func (o *openshiftBuilderManager) addExternalResources(config *buildv1.BuildConfig, workflow *operatorapi.SonataFlow) error { - var configMapSources []buildv1.ConfigMapBuildSource - for _, workflowRes := range workflow.Spec.Resources.ConfigMaps { - configMapSources = append(configMapSources, buildv1.ConfigMapBuildSource{ - ConfigMap: workflowRes.ConfigMap, - DestinationDir: workflowRes.WorkflowPath, - }) - } - //make the workflow properties available to the OpenShift build config. - configMapSources = append(configMapSources, buildv1.ConfigMapBuildSource{ - ConfigMap: corev1.LocalObjectReference{Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow)}, - DestinationDir: ""}) - configMapSources = append(configMapSources, buildv1.ConfigMapBuildSource{ - ConfigMap: corev1.LocalObjectReference{Name: workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow)}, - DestinationDir: ""}) - - config.Spec.Source.ConfigMaps = configMapSources - return nil -} - -func (o *openshiftBuilderManager) Reconcile(build *operatorapi.SonataFlowBuild) (err error) { - var openshiftBuild *buildv1.Build - - if build.Status.BuildPhase == operatorapi.BuildPhaseNone || - build.Status.BuildPhase == operatorapi.BuildPhaseInitialization { - - // guard to avoid spamming multiple builds - if openshiftBuild, err = o.fetchOpenShiftBuildRef(build); err != nil { - return err - } - if openshiftBuild.Status.Phase == buildv1.BuildPhaseNew || - openshiftBuild.Status.Phase == buildv1.BuildPhaseRunning || - openshiftBuild.Status.Phase == buildv1.BuildPhasePending { - build.Status.BuildPhase = operatorapi.BuildPhaseRunning - return nil - } - - // we push another one - workflow, err := o.fetchWorkflowForBuild(build) - if err != nil { - return err - } - // kick a new build - openshiftBuild, err = o.pushNewOpenShiftBuildForWorkflow(build, workflow) - if err != nil { - return err - } - build.Status.BuildPhase = operatorapi.BuildPhaseScheduling - build.Status.ImageTag = openshiftBuild.Status.OutputDockerImageReference - return build.Status.SetInnerBuild(kubeutil.ToTypedLocalReference(openshiftBuild)) - } - - if openshiftBuild, err = o.fetchOpenShiftBuildRef(build); err != nil { - return err - } - if openshiftBuild == nil { - build.Status.BuildPhase = operatorapi.BuildPhaseInitialization - return nil - } - - // Checks the phase - build.Status.BuildPhase = openshiftBuildPhaseMatrix[openshiftBuild.Status.Phase] - if openshiftBuild.Status.Phase == buildv1.BuildPhaseError { - build.Status.Error = openshiftBuild.Status.Message - } - build.Status.ImageTag = openshiftBuild.Status.OutputDockerImageReference - - return build.Status.SetInnerBuild(kubeutil.ToTypedLocalReference(openshiftBuild)) -} - -func (o *openshiftBuilderManager) fetchOpenShiftBuildRef(build *operatorapi.SonataFlowBuild) (*buildv1.Build, error) { - openshiftBuild := &buildv1.Build{} - refOpenShiftBuild := &corev1.TypedLocalObjectReference{} - if err := build.Status.GetInnerBuild(refOpenShiftBuild); err != nil { - return nil, err - } - if err := o.client.Get(o.ctx, types.NamespacedName{Name: refOpenShiftBuild.Name, Namespace: build.Namespace}, openshiftBuild); err != nil { - if errors.IsNotFound(err) { - return openshiftBuild, nil - } - return nil, err - } - return openshiftBuild, nil -} - -// TODO: this should be from fileS, in this case we can TAR everything in a temp directory within the operator pod fs and push -// TODO: for now, we mount the CMs from the devmode into the build and push only the bytes for the workflow definition from memory -func (o *openshiftBuilderManager) pushNewOpenShiftBuildForWorkflow(build *operatorapi.SonataFlowBuild, workflow *operatorapi.SonataFlow) (*buildv1.Build, error) { - options := &buildv1.BinaryBuildRequestOptions{ - ObjectMeta: metav1.ObjectMeta{ - Name: build.Name, Namespace: build.Namespace, - }, - AsFile: workflow.Name + workflowdef.KogitoWorkflowJSONFileExt, - Message: defaultBuildMessageTrigger, - } - workflowDef, err := workflowdef.GetJSONWorkflow(workflow, o.ctx) - if err != nil { - return nil, err - } - - result := &buildv1.Build{} - err = o.buildClient.RESTClient().Post(). - Namespace(build.Namespace). - Resource("buildconfigs"). - Name(build.Name). - SubResource("instantiatebinary"). - Body(strings.NewReader(string(workflowDef))). - VersionedParams(options, runtime.NewParameterCodec(o.client.Scheme())). - Do(context.TODO()). - Into(result) - - return result, err -} diff --git a/internal/controller/builder/openshiftbuilder_test.go b/internal/controller/builder/openshiftbuilder_test.go deleted file mode 100644 index 7e5b8c06..00000000 --- a/internal/controller/builder/openshiftbuilder_test.go +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 builder - -import ( - "context" - "testing" - - buildv1 "github.com/openshift/api/build/v1" - imgv1 "github.com/openshift/api/image/v1" - buildfake "github.com/openshift/client-go/build/clientset/versioned/fake" - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - "github.com/kubesmarts/logic-operator/test" -) - -func Test_openshiftBuilderManager_Reconcile(t *testing.T) { - // Setup - ns := t.Name() - workflow := test.GetBaseSonataFlow(ns) - platform := test.GetBasePlatformInReadyPhase(t.Name()) - config := test.GetSonataFlowBuilderConfig(ns) - namespacedName := types.NamespacedName{Namespace: workflow.Namespace, Name: workflow.Name} - client := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, platform, config).Build() - buildClient := buildfake.NewSimpleClientset().BuildV1() - - managerContext := buildManagerContext{ - ctx: context.TODO(), - client: client, - platform: platform, - builderConfigMap: config, - } - - buildManager := newOpenShiftBuilderManagerWithClient(managerContext, buildClient) - // End Setup - - // Schedule a build - kogitoBuildManager := NewSonataFlowBuildManager(context.TODO(), client) - kbuild, err := kogitoBuildManager.GetOrCreateBuild(workflow) - assert.NoError(t, err) - assert.NotNil(t, kbuild) - assert.NoError(t, buildManager.Schedule(kbuild)) - assert.NoError(t, client.Update(context.TODO(), kbuild)) - assert.Equal(t, operatorapi.BuildPhaseInitialization, kbuild.Status.BuildPhase) - - // Verify if we have the BC and IS - bc := &buildv1.BuildConfig{} - assert.NoError(t, client.Get(context.TODO(), namespacedName, bc)) - is := &imgv1.ImageStream{} - assert.NoError(t, client.Get(context.TODO(), namespacedName, is)) - assert.Contains(t, *bc.Spec.Source.Dockerfile, "FROM "+workflowdef.GetDefaultWorkflowBuilderImageTag()+" AS builder") - - // Reconcile - // unfortunately, the fake buildclient doesn't implement the RESTAPI, thus we can't push a new build to it - // so we emulate. - ocpBuild := &buildv1.Build{ - ObjectMeta: metav1.ObjectMeta{Name: namespacedName.Name, Namespace: namespacedName.Namespace}, - Spec: buildv1.BuildSpec{}, - Status: buildv1.BuildStatus{ - Phase: buildv1.BuildPhaseRunning, - }, - } - assert.NoError(t, client.Create(context.TODO(), ocpBuild)) - kbuild.Status.BuildPhase = operatorapi.BuildPhaseRunning - assert.NoError(t, kbuild.Status.SetInnerBuild(ocpBuild)) - assert.NoError(t, buildManager.Reconcile(kbuild)) - assert.NoError(t, client.Update(context.TODO(), kbuild)) - - assert.NotNil(t, kbuild.Status.InnerBuild.Raw) -} - -func Test_openshiftbuilder_externalCMs(t *testing.T) { - ns := t.Name() - workflow := test.GetBaseSonataFlow(ns) - platform := test.GetBasePlatformInReadyPhase(t.Name()) - config := test.GetSonataFlowBuilderConfig(ns) - externalCm := &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "myopenapis", - Namespace: ns, - }, - } - workflow.Spec.Resources.ConfigMaps = append(workflow.Spec.Resources.ConfigMaps, - operatorapi.ConfigMapWorkflowResource{ConfigMap: v1.LocalObjectReference{Name: externalCm.Name}, WorkflowPath: "specs"}) - - namespacedName := types.NamespacedName{Namespace: workflow.Namespace, Name: workflow.Name} - client := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, platform, config, externalCm).Build() - buildClient := buildfake.NewSimpleClientset().BuildV1() - - managerContext := buildManagerContext{ - ctx: context.TODO(), - client: client, - platform: platform, - builderConfigMap: config, - } - - buildManager := newOpenShiftBuilderManagerWithClient(managerContext, buildClient) - // End Setup - - // Schedule a build - kogitoBuildManager := NewSonataFlowBuildManager(context.TODO(), client) - kbuild, err := kogitoBuildManager.GetOrCreateBuild(workflow) - assert.NoError(t, err) - - assert.NoError(t, buildManager.Schedule(kbuild)) - - bc := &buildv1.BuildConfig{} - assert.NoError(t, client.Get(context.TODO(), namespacedName, bc)) - - assert.Len(t, bc.Spec.Source.ConfigMaps, 3) - assert.Equal(t, "myopenapis", bc.Spec.Source.ConfigMaps[0].ConfigMap.Name) - assert.Equal(t, "specs", bc.Spec.Source.ConfigMaps[0].DestinationDir) - assert.Equal(t, "greeting-props", bc.Spec.Source.ConfigMaps[1].ConfigMap.Name) - assert.Equal(t, "", bc.Spec.Source.ConfigMaps[1].DestinationDir) - assert.Equal(t, "greeting-managed-props", bc.Spec.Source.ConfigMaps[2].ConfigMap.Name) - assert.Equal(t, "", bc.Spec.Source.ConfigMaps[2].DestinationDir) -} - -func Test_openshiftbuilder_forcePull(t *testing.T) { - // Setup - ns := t.Name() - workflow := test.GetBaseSonataFlow(ns) - pl := test.GetBasePlatformInReadyPhase(t.Name()) - config := test.GetSonataFlowBuilderConfig(ns) - - pl.Spec.Build.Config.BaseImage = "image:latest" - - namespacedName := types.NamespacedName{Namespace: workflow.Namespace, Name: workflow.Name} - client := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, pl, config).Build() - buildClient := buildfake.NewSimpleClientset().BuildV1() - managerContext := buildManagerContext{ - ctx: context.TODO(), - client: client, - platform: pl, - builderConfigMap: config, - } - - buildManager := newOpenShiftBuilderManagerWithClient(managerContext, buildClient) - // End Setup - - // Schedule a build - kogitoBuildManager := NewSonataFlowBuildManager(context.TODO(), client) - kbuild, err := kogitoBuildManager.GetOrCreateBuild(workflow) - assert.NoError(t, err) - assert.NotNil(t, kbuild) - assert.NoError(t, buildManager.Schedule(kbuild)) - - bc := &buildv1.BuildConfig{} - assert.NoError(t, client.Get(context.TODO(), namespacedName, bc)) - - // verify if we set force pull to BC - assert.True(t, bc.Spec.Strategy.DockerStrategy.ForcePull) -} diff --git a/internal/controller/cfg/controllers_cfg.go b/internal/controller/cfg/controllers_cfg.go deleted file mode 100644 index ec812d23..00000000 --- a/internal/controller/cfg/controllers_cfg.go +++ /dev/null @@ -1,153 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -// note: we use `cfg` instead of `config` or `configuration` in order to have a shorter accessor in the codebase. - -package cfg - -import ( - "bytes" - "fmt" - "os" - "strings" - - "github.com/imdario/mergo" - "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/log" -) - -const ( - defaultConfigMountPath = "/config/controllers_cfg.yaml" -) - -var controllersCfg *ControllersCfg - -var defaultControllersCfg = &ControllersCfg{ - HealthFailureThresholdDevMode: 50, - DefaultPvcKanikoSize: "1Gi", - KanikoDefaultWarmerImageTag: "gcr.io/kaniko-project/warmer:v1.9.0", - KanikoExecutorImageTag: "gcr.io/kaniko-project/executor:v1.9.0", - JobsServicePostgreSQLImageTag: getEnvOrDefault("RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL", ""), - JobsServiceEphemeralImageTag: getEnvOrDefault("RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL", ""), - DataIndexPostgreSQLImageTag: getEnvOrDefault("RELATED_IMAGE_DATA_INDEX_POSTGRESQL", ""), - DataIndexEphemeralImageTag: getEnvOrDefault("RELATED_IMAGE_DATA_INDEX_EPHEMERAL", ""), - DbMigratorToolImageTag: getEnvOrDefault("RELATED_IMAGE_DB_MIGRATOR_TOOL", ""), - SonataFlowBaseBuilderImageTag: getEnvOrDefault("RELATED_IMAGE_BASE_BUILDER", ""), - SonataFlowDevModeImageTag: getEnvOrDefault("RELATED_IMAGE_DEVMODE", ""), - BuilderConfigMapName: "sonataflow-operator-builder-config", - KogitoEventsGrouping: true, - KogitoEventsGroupingBinary: true, - KogitoEventsGroupingCompress: false, -} - -type GroupArtifactId struct { - GroupId string `yaml:"groupId,omitempty"` - ArtifactId string `yaml:"artifactId,omitempty"` -} - -func (g *GroupArtifactId) String() string { - return fmt.Sprintf("%s:%s", g.GroupId, g.ArtifactId) -} - -type ControllersCfg struct { - DefaultPvcKanikoSize string `yaml:"defaultPvcKanikoSize,omitempty"` - HealthFailureThresholdDevMode int32 `yaml:"healthFailureThresholdDevMode,omitempty"` - KanikoDefaultWarmerImageTag string `yaml:"kanikoDefaultWarmerImageTag,omitempty"` - KanikoExecutorImageTag string `yaml:"kanikoExecutorImageTag,omitempty"` - JobsServicePostgreSQLImageTag string `yaml:"jobsServicePostgreSQLImageTag,omitempty"` - JobsServiceEphemeralImageTag string `yaml:"jobsServiceEphemeralImageTag,omitempty"` - DataIndexPostgreSQLImageTag string `yaml:"dataIndexPostgreSQLImageTag,omitempty"` - DataIndexEphemeralImageTag string `yaml:"dataIndexEphemeralImageTag,omitempty"` - DbMigratorToolImageTag string `yaml:"dbMigratorToolImageTag,omitempty"` - SonataFlowBaseBuilderImageTag string `yaml:"sonataFlowBaseBuilderImageTag,omitempty"` - SonataFlowDevModeImageTag string `yaml:"sonataFlowDevModeImageTag,omitempty"` - BuilderConfigMapName string `yaml:"builderConfigMapName,omitempty"` - PostgreSQLPersistenceExtensions []GroupArtifactId `yaml:"postgreSQLPersistenceExtensions,omitempty"` - KogitoEventsGrouping bool `yaml:"kogitoEventsGrouping,omitempty"` - KogitoEventsGroupingBinary bool `yaml:"KogitoEventsGroupingBinary,omitempty"` - KogitoEventsGroupingCompress bool `yaml:"KogitoEventsGroupingCompress,omitempty"` -} - -// InitializeControllersCfg initializes the platform configuration for this instance. -// Must be called at the main initialization point. -// -// For the main initialization, the configuration is discarded since the controllers will read the cache instance. -// We keep the pointer return here to make sure we can access it from tests if needed or implement an optional use the defaults if fail to read. -func InitializeControllersCfg() (*ControllersCfg, error) { - return InitializeControllersCfgAt(defaultConfigMountPath) -} - -// InitializeControllersCfgAt same as InitializeControllersCfg receiving a path as input. -func InitializeControllersCfgAt(configFilePath string) (*ControllersCfg, error) { - if len(configFilePath) == 0 { - configFilePath = defaultConfigMountPath - } - controllersCfg = nil - yamlFile, err := os.ReadFile(configFilePath) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to read controllers config file", "YAML file location", defaultConfigMountPath) - return defaultControllersCfg, err - } - err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(&controllersCfg) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to unmarshal controllers config file", "YAML file location", defaultConfigMountPath) - return defaultControllersCfg, err - } - - useEnvVarIfConfigEmpty(controllersCfg) - - if err = mergo.Merge(controllersCfg, defaultControllersCfg); err != nil { - return defaultControllersCfg, err - } - return controllersCfg, nil -} - -func GetCfg() *ControllersCfg { - // Guard to use defaults in local tests - // In runtime, cmd/main.go calls InitializeControllersCfg to set the cache. - if controllersCfg == nil { - return defaultControllersCfg - } - return controllersCfg -} - -// useEnvVarIfConfigEmpty overrides the image tags in case the YAML configuration is empty or null with env vars injected into the pod by the OLM Operator. -func useEnvVarIfConfigEmpty(cfg *ControllersCfg) { - cfg.JobsServicePostgreSQLImageTag = fallback(cfg.JobsServicePostgreSQLImageTag, os.Getenv("RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL")) - cfg.JobsServiceEphemeralImageTag = fallback(cfg.JobsServiceEphemeralImageTag, os.Getenv("RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL")) - cfg.DataIndexPostgreSQLImageTag = fallback(cfg.DataIndexPostgreSQLImageTag, os.Getenv("RELATED_IMAGE_DATA_INDEX_POSTGRESQL")) - cfg.DataIndexEphemeralImageTag = fallback(cfg.DataIndexEphemeralImageTag, os.Getenv("RELATED_IMAGE_DATA_INDEX_EPHEMERAL")) - cfg.DbMigratorToolImageTag = fallback(cfg.DbMigratorToolImageTag, os.Getenv("RELATED_IMAGE_DB_MIGRATOR_TOOL")) - cfg.SonataFlowBaseBuilderImageTag = fallback(cfg.SonataFlowBaseBuilderImageTag, os.Getenv("RELATED_IMAGE_BASE_BUILDER")) - cfg.SonataFlowDevModeImageTag = fallback(cfg.SonataFlowDevModeImageTag, os.Getenv("RELATED_IMAGE_DEVMODE")) -} - -func getEnvOrDefault(envKey, defaultVal string) string { - if val := strings.TrimSpace(os.Getenv(envKey)); val != "" { - return val - } - return defaultVal -} - -func fallback(currentVal, envVal string) string { - if strings.TrimSpace(currentVal) != "" { - return currentVal - } - return strings.TrimSpace(envVal) -} diff --git a/internal/controller/cfg/controllers_cfg_test.go b/internal/controller/cfg/controllers_cfg_test.go deleted file mode 100644 index 0e81299c..00000000 --- a/internal/controller/cfg/controllers_cfg_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 cfg - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestInitializeControllersCfgAt_ValidFile(t *testing.T) { - cfg, err := InitializeControllersCfgAt("./testdata/controllers-cfg-test.yaml") - assert.NoError(t, err) - assert.NotNil(t, cfg) - - assert.Equal(t, int32(555), cfg.HealthFailureThresholdDevMode) - assert.Equal(t, "2Gi", cfg.DefaultPvcKanikoSize) - assert.Equal(t, "local/jobs-service:1.0.0", cfg.JobsServicePostgreSQLImageTag) - assert.Equal(t, "local/data-index:1.0.0", cfg.DataIndexPostgreSQLImageTag) - assert.Equal(t, "local/sonataflow-builder:1.0.0", cfg.SonataFlowBaseBuilderImageTag) - assert.Equal(t, "local/sonataflow-devmode:1.0.0", cfg.SonataFlowDevModeImageTag) - assert.Equal(t, 3, len(cfg.PostgreSQLPersistenceExtensions)) - postgresExtensions := cfg.PostgreSQLPersistenceExtensions - assert.Equal(t, GroupArtifactId{ - GroupId: "io.quarkus", - ArtifactId: "quarkus-jdbc-postgresql", - }, postgresExtensions[0]) - - assert.Equal(t, GroupArtifactId{ - GroupId: "io.quarkus", - ArtifactId: "quarkus-agroal", - }, postgresExtensions[1]) - - assert.Equal(t, GroupArtifactId{ - GroupId: "org.kie", - ArtifactId: "kie-addons-quarkus-persistence-jdbc", - }, postgresExtensions[2]) - assert.True(t, cfg.KogitoEventsGrouping) - assert.True(t, cfg.KogitoEventsGroupingBinary) - assert.False(t, cfg.KogitoEventsGroupingCompress) -} - -func TestInitializeControllersCfgAt_FileNotFound(t *testing.T) { - cfg, err := InitializeControllersCfgAt("./whatever.yaml") - assert.Error(t, err) - assert.NotNil(t, cfg) //get the default - assert.True(t, os.IsNotExist(err)) - // defaults - assert.Equal(t, defaultControllersCfg, cfg) -} - -func TestInitializeControllersCfgAt_NotValidYaml(t *testing.T) { - cfg, err := InitializeControllersCfgAt("./testdata/controllers-cfg-invalid.yaml") - assert.NoError(t, err) - assert.NotNil(t, cfg) - // defaults - assert.Equal(t, defaultControllersCfg, cfg) -} diff --git a/internal/controller/cfg/testdata/controllers-cfg-invalid.yaml b/internal/controller/cfg/testdata/controllers-cfg-invalid.yaml deleted file mode 100644 index 05454515..00000000 --- a/internal/controller/cfg/testdata/controllers-cfg-invalid.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -anyThingNotValid: "true" diff --git a/internal/controller/cfg/testdata/controllers-cfg-test.yaml b/internal/controller/cfg/testdata/controllers-cfg-test.yaml deleted file mode 100644 index b6d76a7e..00000000 --- a/internal/controller/cfg/testdata/controllers-cfg-test.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# The default size of Kaniko PVC when using the internal operator builder manager -defaultPvcKanikoSize: 2Gi -healthFailureThresholdDevMode: 555 -kanikoDefaultWarmerImageTag: gcr.io/kaniko-project/warmer:v1.0.0 -kanikoExecutorImageTag: gcr.io/kaniko-project/executor:v1.0.0 -jobsServicePostgreSQLImageTag: "local/jobs-service:1.0.0" -dataIndexPostgreSQLImageTag: "local/data-index:1.0.0" -sonataFlowBaseBuilderImageTag: "local/sonataflow-builder:1.0.0" -sonataFlowDevModeImageTag: "local/sonataflow-devmode:1.0.0" -postgreSQLPersistenceExtensions: - - groupId: io.quarkus - artifactId: quarkus-jdbc-postgresql - - groupId: io.quarkus - artifactId: quarkus-agroal - - groupId: org.kie - artifactId: kie-addons-quarkus-persistence-jdbc -kogitoEventsGrouping: true -kogitoEventsGroupingBinary: true -kogitoEventsGroupingCompress: false diff --git a/internal/controller/clusterplatform/action.go b/internal/controller/clusterplatform/action.go deleted file mode 100644 index acaf9adb..00000000 --- a/internal/controller/clusterplatform/action.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 clusterplatform - -import ( - "context" - - "github.com/kubesmarts/logic-operator/container-builder/client" - - v08 "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -// Action --. -type Action interface { - client.Injectable - - // a user friendly name for the action - Name() string - - // returns true if the action can handle the cluster platform - CanHandle(ctx context.Context, cPlatform *v08.SonataFlowClusterPlatform) bool - - // executes the handling function - Handle(ctx context.Context, cPlatform *v08.SonataFlowClusterPlatform) error -} - -type baseAction struct { - client client.Client -} - -func (action *baseAction) InjectClient(client client.Client) { - action.client = client -} diff --git a/internal/controller/clusterplatform/clusterplatform.go b/internal/controller/clusterplatform/clusterplatform.go deleted file mode 100644 index 6435b8f6..00000000 --- a/internal/controller/clusterplatform/clusterplatform.go +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 clusterplatform - -import ( - "context" - - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" -) - -const ( - PlatformServices operatorapi.WorkFlowCapability = "services" -) - -// GetActiveClusterPlatform returns the currently installed active cluster platform. -func GetActiveClusterPlatform(ctx context.Context) (*operatorapi.SonataFlowClusterPlatform, error) { - return getClusterPlatform(ctx, true) -} - -// getClusterPlatform returns the currently active cluster platform or any cluster platform existing in the cluster. -func getClusterPlatform(ctx context.Context, active bool) (*operatorapi.SonataFlowClusterPlatform, error) { - klog.V(log.D).InfoS("Finding available cluster platforms") - - lst, err := listPrimaryClusterPlatforms(ctx) - if err != nil { - return nil, err - } - - for _, cPlatform := range lst.Items { - if IsActive(&cPlatform) { - klog.V(log.D).InfoS("Found active cluster platform", "platform", cPlatform.Name) - return &cPlatform, nil - } - } - - if !active && len(lst.Items) > 0 { - // does not require the cluster platform to be active, just return one if present - res := lst.Items[0] - klog.V(log.D).InfoS("Found cluster platform", "platform", res.Name) - return &res, nil - } - klog.V(log.I).InfoS("No cluster platform found") - return nil, k8serrors.NewNotFound(operatorapi.Resource(operatorapi.SonataFlowClusterPlatformKind), "") -} - -// listPrimaryClusterPlatforms returns all non-secondary cluster platforms installed (only one will be active). -func listPrimaryClusterPlatforms(ctx context.Context) (*operatorapi.SonataFlowClusterPlatformList, error) { - lst, err := listAllClusterPlatforms(ctx) - if err != nil { - return nil, err - } - - filtered := &operatorapi.SonataFlowClusterPlatformList{} - for i := range lst.Items { - cPl := lst.Items[i] - if !IsSecondary(&cPl) { - filtered.Items = append(filtered.Items, cPl) - } - } - return filtered, nil -} - -// allDuplicatedClusterPlatforms returns true if every cluster platform has a "Duplicated" status set -func allDuplicatedClusterPlatforms(ctx context.Context) bool { - lst, err := listAllClusterPlatforms(ctx) - if err != nil { - return false - } - - for i := range lst.Items { - if !lst.Items[i].Status.IsDuplicated() { - return false - } - } - - return true -} - -// listAllClusterPlatforms returns all clusterplatforms installed. -func listAllClusterPlatforms(ctx context.Context) (*operatorapi.SonataFlowClusterPlatformList, error) { - lst := operatorapi.NewSonataFlowClusterPlatformList() - if err := utils.GetClient().List(ctx, &lst); err != nil { - return nil, err - } - return &lst, nil -} - -// IsActive determines if the given cluster platform is being used. -func IsActive(p *operatorapi.SonataFlowClusterPlatform) bool { - return p.Status.IsReady() && !p.Status.IsDuplicated() -} - -// IsSecondary determines if the given cluster platform is marked as secondary. -func IsSecondary(p *operatorapi.SonataFlowClusterPlatform) bool { - if l, ok := p.Annotations[metadata.SecondaryPlatformAnnotation]; ok && l == "true" { - return true - } - return false -} diff --git a/internal/controller/clusterplatform/defaults.go b/internal/controller/clusterplatform/defaults.go deleted file mode 100644 index f4998b59..00000000 --- a/internal/controller/clusterplatform/defaults.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 clusterplatform - -import ( - "context" - - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/log" -) - -func configureDefaults(ctx context.Context, c client.Client, cp *operatorapi.SonataFlowClusterPlatform, verbose bool) error { - if cp.Spec.Capabilities == nil { - cp.Spec.Capabilities = &operatorapi.SonataFlowClusterPlatformCapSpec{ - Workflows: []operatorapi.WorkFlowCapability{PlatformServices}, - } - } - - return updateClusterPlatform(ctx, c, cp) -} - -func updateClusterPlatform(ctx context.Context, c client.Client, cp *operatorapi.SonataFlowClusterPlatform) error { - sfcPlatform := operatorapi.SonataFlowClusterPlatform{} - if err := c.Get(ctx, ctrl.ObjectKey{Namespace: cp.Namespace, Name: cp.Name}, &sfcPlatform); err != nil { - klog.V(log.E).ErrorS(err, "Error reading the Cluster Platform") - return err - } - - sfcPlatform.Spec = cp.Spec - if err := c.Update(ctx, &sfcPlatform); err != nil { - klog.V(log.E).ErrorS(err, "Error updating the Cluster Platform") - } - - return nil -} diff --git a/internal/controller/clusterplatform/initialize.go b/internal/controller/clusterplatform/initialize.go deleted file mode 100644 index eb041275..00000000 --- a/internal/controller/clusterplatform/initialize.go +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 clusterplatform - -import ( - "context" - "fmt" - - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/api" - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -// NewInitializeAction returns an action that initializes the platform configuration when not provided by the user. -func NewInitializeAction() Action { - return &initializeAction{} -} - -type initializeAction struct { - baseAction -} - -func (action *initializeAction) Name() string { - return "initialize" -} - -func (action *initializeAction) CanHandle(ctx context.Context, cPlatform *operatorapi.SonataFlowClusterPlatform) bool { - return !cPlatform.Status.IsDuplicated() || allDuplicatedClusterPlatforms(ctx) -} - -func (action *initializeAction) Handle(ctx context.Context, cPlatform *operatorapi.SonataFlowClusterPlatform) error { - duplicate, err := action.isPrimaryDuplicate(ctx, cPlatform) - if err != nil { - return err - } - if duplicate { - // another cluster platform already present - if !cPlatform.Status.IsDuplicated() { - cPlatform.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformDuplicatedReason, "") - } - return nil - } - - if err = configureDefaults(ctx, action.client, cPlatform, true); err != nil { - return err - } - cPlatform.Status.Version = metadata.SpecVersion - platformRef := cPlatform.Spec.PlatformRef - - // Check referenced platform status - platform := &operatorapi.SonataFlowPlatform{} - err = action.client.Get(ctx, types.NamespacedName{Namespace: platformRef.Namespace, Name: platformRef.Name}, platform) - if err != nil { - if k8serrors.IsNotFound(err) { - klog.V(log.D).InfoS("%s platform does not exist in %s namespace.", platformRef.Name, platformRef.Namespace) - cPlatform.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformNotFoundReason, - fmt.Sprintf("%s platform does not exist in %s namespace.", platformRef.Name, platformRef.Namespace)) - return nil - } - return err - } - - if platform != nil { - condition := platform.Status.GetTopLevelCondition() - if condition.IsTrue() { - klog.V(log.D).InfoS("Referenced SonataFlowPlatform '%s/%s' is ready", platformRef.Namespace, platformRef.Name) - cPlatform.Status.Manager().MarkTrueWithReasonf(api.SucceedConditionType, "", - "Referenced SonataFlowPlatform '%s/%s' is ready", platformRef.Namespace, platformRef.Name) - } else if condition.IsFalse() { - klog.V(log.D).InfoS("Referenced SonataFlowPlatform '%s/%s' not ready", platformRef.Namespace, platformRef.Name) - cPlatform.Status.Manager().MarkFalsef(api.SucceedConditionType, operatorapi.PlatformFailureReason, - "Referenced SonataFlowPlatform '%s/%s' not ready", platformRef.Namespace, platformRef.Name) - } else { - klog.V(log.D).InfoS("Waiting for referenced SonataFlowPlatform '%s/%s' to be ready", platformRef.Namespace, platformRef.Name) - cPlatform.Status.Manager().MarkUnknownf(api.SucceedConditionType, operatorapi.PlatformWarmingReason, - "Waiting for referenced SonataFlowPlatform '%s/%s' to be ready", platformRef.Namespace, platformRef.Name) - } - } - - return nil -} - -// Function to double-check if there is already an active cluster platform -func (action *initializeAction) isPrimaryDuplicate(ctx context.Context, cPlatform *operatorapi.SonataFlowClusterPlatform) (bool, error) { - if IsSecondary(cPlatform) { - // Always reconcile secondary cluster platforms - return false, nil - } - platforms, err := listPrimaryClusterPlatforms(ctx) - if err != nil { - return false, err - } - for _, p := range platforms.Items { - p := p // pin - if p.Name != cPlatform.Name && IsActive(&p) { - return true, nil - } - } - - return false, nil -} diff --git a/internal/controller/const.go b/internal/controller/const.go deleted file mode 100644 index 48fe766c..00000000 --- a/internal/controller/const.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 - -const ( - // ComponentName just a name to identify this package/component/application - ComponentName = "sonataflow-manager" -) diff --git a/internal/controller/discovery/discovery.go b/internal/controller/discovery/discovery.go deleted file mode 100644 index 6d5dba33..00000000 --- a/internal/controller/discovery/discovery.go +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - - "k8s.io/client-go/rest" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - KnativeScheme = "knative" - KubernetesScheme = "kubernetes" - OpenshiftScheme = "openshift" - - // PortQueryParam well known query param to select a particular target port, for example when a service is being - // discovered and there are many ports to select. - PortQueryParam = "port" - - // KubernetesDNSAddress use this output format with kubernetes services and pods to resolve to the corresponding - // kubernetes DNS name. see: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ - KubernetesDNSAddress = "KubernetesDNSAddress" - - // KubernetesIPAddress default format, resolves objects addresses to the corresponding cluster IP address. - KubernetesIPAddress = "KubernetesIPAddress" - - // kubernetes groups - kubernetesServices = "kubernetes:services.v1" - kubernetesPods = "kubernetes:pods.v1" - kubernetesDeployments = "kubernetes:deployments.v1.apps" - kubernetesStatefulSets = "kubernetes:statefulsets.v1.apps" - kubernetesIngresses = "kubernetes:ingresses.v1.networking.k8s.io" - - // knative groups - knativeServices = "knative:services.v1.serving.knative.dev" - knativeBrokers = "knative:brokers.v1.eventing.knative.dev" - - // openshift groups - openshiftRoutes = "openshift:routes.v1.route.openshift.io" - openshiftDeploymentConfigs = "openshift:deploymentconfigs.v1.apps.openshift.io" -) - -type ResourceUri struct { - Scheme string - GVK v1.GroupVersionKind - Namespace string - Name string - QueryParams map[string]string -} - -// ServiceCatalog is the entry point to resolve resource addresses given a ResourceUri. -type ServiceCatalog interface { - // Query returns the address corresponding to the resource identified by the uri. In the case of services or pods, - // the outputFormat can be used to determine the type of address to calculate. - // If the outputFormat is KubernetesDNSAddress, the returned value for a service will be like this: http://my-service.my-namespace.svc:8080, - // and the returned value for pod will be like this: http://10-244-1-135.my-namespace.pod.cluster.local:8080. - // If the outputFormat is KubernetesIPAddress, the returned value for pods and services, and other resource types, - // will be like this: http://10.245.1.132:8080 - Query(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) -} - -type sonataFlowServiceCatalog struct { - kubernetesCatalog ServiceCatalog - knativeCatalog ServiceCatalog - openshiftCatalog ServiceCatalog -} - -// NewServiceCatalog returns a new ServiceCatalog configured to resolve kubernetes, knative, and openshift resource addresses. -func NewServiceCatalog(cli client.Client, knDiscoveryClient *KnDiscoveryClient, openShiftDiscoveryClient *OpenShiftDiscoveryClient) ServiceCatalog { - return &sonataFlowServiceCatalog{ - kubernetesCatalog: newK8SServiceCatalog(cli), - knativeCatalog: newKnServiceCatalog(knDiscoveryClient), - openshiftCatalog: newOpenShiftServiceCatalog(openShiftDiscoveryClient), - } -} - -func NewServiceCatalogForConfig(cli client.Client, cfg *rest.Config) ServiceCatalog { - return &sonataFlowServiceCatalog{ - kubernetesCatalog: newK8SServiceCatalog(cli), - knativeCatalog: newKnServiceCatalogForConfig(cfg), - openshiftCatalog: newOpenShiftServiceCatalogForClientAndConfig(cli, cfg), - } -} - -func (c *sonataFlowServiceCatalog) Query(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - switch uri.Scheme { - case KubernetesScheme: - return c.kubernetesCatalog.Query(ctx, uri, outputFormat) - case KnativeScheme: - return c.knativeCatalog.Query(ctx, uri, outputFormat) - case OpenshiftScheme: - return c.openshiftCatalog.Query(ctx, uri, outputFormat) - default: - return "", fmt.Errorf("unknown scheme was provided for service discovery: %s", uri.Scheme) - } -} - -type ResourceUriBuilder struct { - uri *ResourceUri -} - -func NewResourceUriBuilder(scheme string) ResourceUriBuilder { - return ResourceUriBuilder{ - uri: &ResourceUri{ - Scheme: scheme, - GVK: v1.GroupVersionKind{}, - QueryParams: map[string]string{}, - }, - } -} - -func (b ResourceUriBuilder) Kind(kind string) ResourceUriBuilder { - b.uri.GVK.Kind = kind - return b -} - -func (b ResourceUriBuilder) Version(version string) ResourceUriBuilder { - b.uri.GVK.Version = version - return b -} - -func (b ResourceUriBuilder) Group(group string) ResourceUriBuilder { - b.uri.GVK.Group = group - return b -} - -func (b ResourceUriBuilder) Namespace(namespace string) ResourceUriBuilder { - b.uri.Namespace = namespace - return b -} - -func (b ResourceUriBuilder) Name(name string) ResourceUriBuilder { - b.uri.Name = name - return b -} - -func (b ResourceUriBuilder) WithPort(customPort string) ResourceUriBuilder { - b.uri.SetPort(customPort) - return b -} - -func (b ResourceUriBuilder) WithQueryParam(param string, value string) ResourceUriBuilder { - b.uri.AddQueryParam(param, value) - return b -} - -func (b ResourceUriBuilder) Build() *ResourceUri { - return b.uri -} - -func (r *ResourceUri) AddQueryParam(name string, value string) { - if len(value) > 0 { - r.QueryParams[name] = value - } -} - -func (r *ResourceUri) GetQueryParam(name string) string { - if len(name) > 0 { - return r.QueryParams[name] - } - return "" -} - -func (r *ResourceUri) SetPort(value string) { - r.AddQueryParam(PortQueryParam, value) -} - -func (r *ResourceUri) GetPort() string { - return r.GetQueryParam(PortQueryParam) -} - -// GetCustomLabels returns all the query parameters that not considered well known query parameters, and thus, has no -// particular semantic during the discovery. These arbitrary parameters are normally considered as labels, and when -// present, and the service discovery must give a preference over a set of resources, they can be used to do a filtering. -// by labels. -func (r *ResourceUri) GetCustomLabels() map[string]string { - customQueryParams := make(map[string]string) - for k, v := range r.QueryParams { - if !isWellKnownQueryParam(k) && len(v) > 0 { - customQueryParams[k] = v - } - } - return customQueryParams -} - -func isWellKnownQueryParam(k string) bool { - return k == PortQueryParam -} - -func (r *ResourceUri) String() string { - if r == nil { - return "" - } - gvk := appendWithDelimiter("", r.GVK.Kind, ".") - gvk = appendWithDelimiter(gvk, r.GVK.Version, ".") - gvk = appendWithDelimiter(gvk, r.GVK.Group, ".") - uri := r.Scheme + ":" + gvk - uri = appendWithDelimiter(uri, r.Namespace, "/") - uri = appendWithDelimiter(uri, r.Name, "/") - - return appendWithDelimiter(uri, buildLabelsString(r.QueryParams, "&"), "?") -} - -func appendWithDelimiter(value string, toAppend string, delimiter string) string { - if len(toAppend) > 0 { - if len(value) > 0 { - return fmt.Sprintf("%s%s%s", value, delimiter, toAppend) - } else { - return fmt.Sprintf("%s%s", value, toAppend) - } - } - return value -} - -func buildParam(name string, value string) string { - return fmt.Sprintf("%s=%s", name, value) -} - -func buildLabelsString(labels map[string]string, delimiter string) string { - var labelsStr string - for name, value := range labels { - labelsStr = appendWithDelimiter(labelsStr, buildParam(name, value), delimiter) - } - return labelsStr -} diff --git a/internal/controller/discovery/discovery_knative_test.go b/internal/controller/discovery/discovery_knative_test.go deleted file mode 100644 index b71c78a6..00000000 --- a/internal/controller/discovery/discovery_knative_test.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "knative.dev/pkg/apis" - - duckv1 "knative.dev/pkg/apis/duck/v1" - - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - - fakeeventingclient "knative.dev/eventing/pkg/client/injection/client/fake" - - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - fakeservingclient "knative.dev/serving/pkg/client/injection/client/fake" -) - -func Test_QueryKnativeService(t *testing.T) { - doTestQueryKnativeService(t, "http://knServiceName1.namespace1.svc.cluster.local") -} - -func Test_QueryKnativeServiceNotFound(t *testing.T) { - _, client := fakeservingclient.With(context.TODO()) - ctg := NewServiceCatalog(nil, newKnDiscoveryClient(client.ServingV1(), nil), nil) - doTestQueryWithError(t, ctg, *NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Group("serving.knative.dev"). - Version("v1"). - Namespace(namespace1). - Name(knServiceName1).Build(), "", fmt.Sprintf("services.serving.knative.dev %q not found", knServiceName1)) -} - -func doTestQueryKnativeService(t *testing.T, expectedUri string) { - service := &servingv1.Service{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace1, - Name: knServiceName1, - }, - Spec: servingv1.ServiceSpec{}, - Status: servingv1.ServiceStatus{ - RouteStatusFields: servingv1.RouteStatusFields{ - Address: &duckv1.Addressable{ - URL: &apis.URL{ - Scheme: "http", - Host: knServiceName1 + "." + namespace1 + ".svc.cluster.local", - }, - }, - }, - }, - } - _, client := fakeservingclient.With(context.TODO(), service) - ctg := NewServiceCatalog(nil, newKnDiscoveryClient(client.ServingV1(), nil), nil) - doTestQuery(t, ctg, *NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Group("serving.knative.dev"). - Version("v1"). - Namespace(namespace1). - Name(knServiceName1).Build(), "", expectedUri) -} - -func Test_QueryKnativeBroker(t *testing.T) { - doTestQueryKnativeBroker(t, "http://broker-ingress.knative-eventing.svc.cluster.local/namespace1/knBrokerName1") -} - -func Test_QueryKnativeBrokerNotFound(t *testing.T) { - _, client := fakeeventingclient.With(context.TODO()) - ctg := NewServiceCatalog(nil, newKnDiscoveryClient(nil, client.EventingV1()), nil) - doTestQueryWithError(t, ctg, *NewResourceUriBuilder(KnativeScheme). - Kind("brokers"). - Group("eventing.knative.dev"). - Version("v1"). - Namespace(namespace1). - Name(knBrokerName1).Build(), "", fmt.Sprintf("brokers.eventing.knative.dev %q not found", knBrokerName1)) -} - -func doTestQueryKnativeBroker(t *testing.T, expectedUri string) { - broker := &eventingv1.Broker{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace1, - Name: knBrokerName1, - }, - Spec: eventingv1.BrokerSpec{}, - Status: eventingv1.BrokerStatus{ - AddressStatus: duckv1.AddressStatus{ - Address: &duckv1.Addressable{ - URL: &apis.URL{ - Scheme: "http", - Host: "broker-ingress.knative-eventing.svc.cluster.local", - Path: "/" + namespace1 + "/" + knBrokerName1, - }, - }, - }, - }, - } - _, client := fakeeventingclient.With(context.TODO(), broker) - ctg := NewServiceCatalog(nil, newKnDiscoveryClient(nil, client.EventingV1()), nil) - doTestQuery(t, ctg, *NewResourceUriBuilder(KnativeScheme). - Kind("brokers"). - Group("eventing.knative.dev"). - Version("v1"). - Namespace(namespace1). - Name(knBrokerName1).Build(), "", expectedUri) -} diff --git a/internal/controller/discovery/discovery_openshift_test.go b/internal/controller/discovery/discovery_openshift_test.go deleted file mode 100644 index 91fbf6cc..00000000 --- a/internal/controller/discovery/discovery_openshift_test.go +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - appsv1 "github.com/openshift/api/apps/v1" - routev1 "github.com/openshift/api/route/v1" - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - fakeappsclient "github.com/openshift/client-go/apps/clientset/versioned/fake" - fakerouteclient "github.com/openshift/client-go/route/clientset/versioned/fake" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "testing" -) - -func Test_QueryOpenShiftRoute(t *testing.T) { - doTestQueryOpenShiftRoute(t, false, "http://openshiftroutehost1") -} - -func Test_QueryOpenShiftRouteWithTLS(t *testing.T) { - doTestQueryOpenShiftRoute(t, true, "https://openshiftroutehost1") -} - -func doTestQueryOpenShiftRoute(t *testing.T, tls bool, expectedUri string) { - route := &routev1.Route{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace1, - Name: openShiftRouteName1, - }, - Spec: routev1.RouteSpec{ - Host: openShiftRouteHost1, - }, - Status: routev1.RouteStatus{}, - } - if tls { - route.Spec.TLS = &routev1.TLSConfig{} - } - fakeRoutesClient := fakerouteclient.NewSimpleClientset(route) - ctg := NewServiceCatalog(nil, nil, newOpenShiftDiscoveryClient(nil, fakeRoutesClient.RouteV1(), nil)) - doTestQuery(t, ctg, *NewResourceUriBuilder(OpenshiftScheme). - Kind("routes"). - Group("route.openshift.io"). - Version("v1"). - Namespace(namespace1). - Name(openShiftRouteName1).Build(), "", expectedUri) -} - -func Test_QueryOpenShiftDeploymentConfigWithServiceDNSMode(t *testing.T) { - doTestQueryOpenShiftDeploymentConfig(t, KubernetesDNSAddress, true, "http://service1Name.namespace1.svc:80", "") -} - -func Test_QueryOpenShiftDeploymentConfigWithServiceIPAddressMode(t *testing.T) { - doTestQueryOpenShiftDeploymentConfig(t, KubernetesIPAddress, true, "http://10.1.15.16:80", "") -} - -func Test_QueryOpenShiftDeploymentConfigWithoutServiceDNSMode(t *testing.T) { - doTestQueryOpenShiftDeploymentConfig(t, KubernetesDNSAddress, false, "", "no service was found for the deploymentConfig: openShiftDeploymentConfigName1") -} - -func Test_QueryOpenShiftDeploymentConfigWithoutServiceIPAddressMode(t *testing.T) { - doTestQueryOpenShiftDeploymentConfig(t, KubernetesIPAddress, false, "", "no service was found for the deploymentConfig: openShiftDeploymentConfigName1") -} - -func doTestQueryOpenShiftDeploymentConfig(t *testing.T, outputFormat string, withService bool, expectedUri string, expectedError string) { - selector := map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - deploymentConfig := &appsv1.DeploymentConfig{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace1, - Name: openShiftDeploymentConfigName1, - }, - Spec: appsv1.DeploymentConfigSpec{ - Selector: selector, - }, - } - fakeClientBuilder := fake.NewClientBuilder() - if withService { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.Selector = selector - service.Spec.ClusterIP = "10.1.15.16" - service.Spec.Type = corev1.ServiceTypeNodePort - fakeClientBuilder.WithRuntimeObjects(service) - } - cli := fakeClientBuilder.Build() - fakeAppsClient := fakeappsclient.NewSimpleClientset(deploymentConfig) - ctg := NewServiceCatalog(nil, nil, newOpenShiftDiscoveryClient(cli, nil, fakeAppsClient.AppsV1())) - - resourceUri := *NewResourceUriBuilder(OpenshiftScheme). - Kind("deploymentconfigs"). - Group("apps.openshift.io"). - Version("v1"). - Namespace(namespace1). - Name(openShiftDeploymentConfigName1).Build() - - if withService { - doTestQuery(t, ctg, resourceUri, outputFormat, expectedUri) - } else { - doTestQueryWithError(t, ctg, resourceUri, outputFormat, expectedError) - } -} diff --git a/internal/controller/discovery/discovery_test.go b/internal/controller/discovery/discovery_test.go deleted file mode 100644 index 12175ca1..00000000 --- a/internal/controller/discovery/discovery_test.go +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/networking/v1" - "sigs.k8s.io/controller-runtime/pkg/client/fake" -) - -func Test_NewResourceUriBuilder(t *testing.T) { - resourceUri := NewResourceUriBuilder(KubernetesScheme). - Kind("deployments"). - Group("apps"). - Version("v1"). - Namespace(namespace1). - Name(service1Name). - WithPort("custom-port-value"). - WithQueryParam(label1, valueLabel1).Build() - - assert.Equal(t, "deployments", resourceUri.GVK.Kind) - assert.Equal(t, "apps", resourceUri.GVK.Group) - assert.Equal(t, "v1", resourceUri.GVK.Version) - assert.Equal(t, namespace1, resourceUri.Namespace) - assert.Equal(t, service1Name, resourceUri.Name) - assert.Equal(t, 2, len(resourceUri.QueryParams)) - assert.Equal(t, "custom-port-value", resourceUri.GetPort()) - assert.Equal(t, valueLabel1, resourceUri.QueryParams[label1]) - assert.Equal(t, 1, len(resourceUri.GetCustomLabels())) - assert.Equal(t, valueLabel1, resourceUri.GetCustomLabels()[label1]) -} - -func Test_QueryKubernetesServiceDNSMode(t *testing.T) { - doTestQueryKubernetesService(t, KubernetesDNSAddress, "http://service1Name.namespace1.svc:80") -} - -func Test_QueryKubernetesServiceIPAddressMode(t *testing.T) { - doTestQueryKubernetesService(t, KubernetesIPAddress, "http://10.1.5.18:80") -} - -func doTestQueryKubernetesService(t *testing.T, outputFormat string, expectedUri string) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.Type = corev1.ServiceTypeNodePort - service.Spec.ClusterIP = "10.1.5.18" - cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build() - ctg := NewServiceCatalog(cli, nil, nil) - doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Namespace(namespace1). - Name(service1Name).Build(), outputFormat, expectedUri) -} - -func Test_QueryKubernetesPodDNSMode(t *testing.T) { - doTestQueryKubernetesPod(t, KubernetesDNSAddress, "http://10-1-12-13.namespace1.pod:80") -} - -func Test_QueryKubernetesPodIPAddressMode(t *testing.T) { - doTestQueryKubernetesPod(t, KubernetesIPAddress, "http://10.1.12.13:80") -} - -func doTestQueryKubernetesPod(t *testing.T, outputFormat string, expectedUri string) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts("container1Name", mockContainerPort(httpProtocol, tcp, defaultHttpPort))) - pod.Status.PodIP = "10.1.12.13" - cli := fake.NewClientBuilder().WithRuntimeObjects(pod).Build() - ctg := NewServiceCatalog(cli, nil, nil) - doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme). - Kind("pods"). - Version("v1"). - Namespace(namespace1). - Name(pod1Name).Build(), outputFormat, expectedUri) -} - -func Test_QueryKubernetesDeploymentWithServiceDNSMode(t *testing.T) { - doTesQueryKubernetesDeploymentWithService(t, KubernetesDNSAddress, "http://service1Name.namespace1.svc:80") -} - -func Test_QueryKubernetesDeploymentWithServiceIPAddressMode(t *testing.T) { - doTesQueryKubernetesDeploymentWithService(t, KubernetesIPAddress, "http://10.1.15.16:80") -} - -func doTesQueryKubernetesDeploymentWithService(t *testing.T, outputFormat string, expectedUri string) { - selector := map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - - deployment := mockDeployment(namespace1, deployment1Name, nil, &selector) - - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.Selector = selector - service.Spec.ClusterIP = "10.1.15.16" - service.Spec.Type = corev1.ServiceTypeNodePort - - cli := fake.NewClientBuilder().WithRuntimeObjects(deployment, service).Build() - ctg := NewServiceCatalog(cli, nil, nil) - - doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme). - Group("apps"). - Version("v1"). - Kind("deployments"). - Namespace(namespace1). - Name(deployment1Name).Build(), - outputFormat, expectedUri) -} - -func Test_QueryKubernetesDeploymentWithoutServiceDNSMode(t *testing.T) { - doTestQueryKubernetesDeploymentWithoutService(t, KubernetesDNSAddress) -} - -func Test_QueryKubernetesDeploymentWithoutServiceIPAddressMode(t *testing.T) { - doTestQueryKubernetesDeploymentWithoutService(t, KubernetesIPAddress) -} - -func doTestQueryKubernetesDeploymentWithoutService(t *testing.T, outputFormat string) { - selector := map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - - deployment := mockDeployment(namespace1, deployment1Name, nil, &selector) - ctg := NewServiceCatalog(fake.NewClientBuilder().WithRuntimeObjects(deployment).Build(), nil, nil) - - uri := *NewResourceUriBuilder(KubernetesScheme). - Group("apps"). - Version("v1"). - Kind("deployments"). - Namespace(namespace1). - Name(deployment1Name).Build() - - doTestQueryWithError(t, ctg, uri, outputFormat, fmt.Sprintf("no service was found for the deployment: %s", uri.Name)) -} - -func Test_QueryKubernetesStatefulSetWithServiceDNSMode(t *testing.T) { - doTestQueryKubernetesStatefulSetWithService(t, KubernetesDNSAddress, "http://service1Name.namespace1.svc:80") -} - -func Test_QueryKubernetesStatefulSetWithServiceIPAddressMode(t *testing.T) { - doTestQueryKubernetesStatefulSetWithService(t, KubernetesIPAddress, "http://10.1.18.19:80") -} - -func doTestQueryKubernetesStatefulSetWithService(t *testing.T, outputFormat string, expectedUri string) { - selector := map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - - statefulSet := mockStatefulSet(namespace1, statefulSet1Name, nil, &selector) - - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.Selector = selector - service.Spec.ClusterIP = "10.1.18.19" - service.Spec.Type = corev1.ServiceTypeNodePort - - cli := fake.NewClientBuilder().WithRuntimeObjects(statefulSet, service).Build() - ctg := NewServiceCatalog(cli, nil, nil) - - doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme). - Group("apps"). - Version("v1"). - Kind("statefulsets"). - Namespace(namespace1). - Name(statefulSet1Name).Build(), - outputFormat, expectedUri) -} - -func Test_QueryKubernetesStatefulSetWithoutServiceDNSMode(t *testing.T) { - doTestQueryKubernetesStatefulSetWithoutService(t, KubernetesDNSAddress) -} - -func Test_QueryKubernetesStatefulSetWithoutServiceIPAddressMode(t *testing.T) { - doTestQueryKubernetesStatefulSetWithoutService(t, KubernetesIPAddress) -} - -func doTestQueryKubernetesStatefulSetWithoutService(t *testing.T, outputFormat string) { - selector := map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - - statefulSet := mockStatefulSet(namespace1, statefulSet1Name, nil, &selector) - ctg := NewServiceCatalog(fake.NewClientBuilder().WithRuntimeObjects(statefulSet).Build(), nil, nil) - - uri := *NewResourceUriBuilder(KubernetesScheme). - Group("apps"). - Version("v1"). - Kind("statefulsets"). - Namespace(namespace1). - Name(statefulSet1Name).Build() - doTestQueryWithError(t, ctg, uri, outputFormat, fmt.Sprintf("no service was found for the statefulset: %s", uri.Name)) -} - -func Test_QueryKubernetesIngressHostNoTLS(t *testing.T) { - doTestQueryKubernetesIngress(t, "myingresshost.com.uy", "", false, KubernetesIPAddress, "http://myingresshost.com.uy:80") -} - -func Test_QueryKubernetesIngressHostWithTLS(t *testing.T) { - doTestQueryKubernetesIngress(t, "myingresshost.com.uy", "", true, KubernetesIPAddress, "https://myingresshost.com.uy:443") -} - -func Test_QueryKubernetesIngressIPNoTLS(t *testing.T) { - doTestQueryKubernetesIngress(t, "", "142.250.184.174", false, KubernetesIPAddress, "http://142.250.184.174:80") -} - -func Test_QueryKubernetesIngressIPWithTLS(t *testing.T) { - doTestQueryKubernetesIngress(t, "", "142.250.184.174", true, KubernetesIPAddress, "https://142.250.184.174:443") -} - -func doTestQueryKubernetesIngress(t *testing.T, hostName string, ip string, tls bool, outputFormat string, expectedUri string) { - ingress := mockIngress(namespace1, ingress1Name) - - ingress.Status.LoadBalancer.Ingress = []v1.IngressLoadBalancerIngress{{Hostname: hostName, IP: ip}} - if tls { - ingress.Spec.TLS = []v1.IngressTLS{{}} - } - cli := fake.NewClientBuilder().WithRuntimeObjects(ingress).Build() - ctg := NewServiceCatalog(cli, nil, nil) - doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme). - Kind("ingresses"). - Group("networking.k8s.io"). - Version("v1"). - Namespace(namespace1). - Name(ingress1Name).Build(), outputFormat, expectedUri) -} - -func doTestQuery(t *testing.T, ctg ServiceCatalog, resourceUri ResourceUri, outputFormat, expectedUri string) { - uri, err := ctg.Query(context.TODO(), resourceUri, outputFormat) - assert.NoError(t, err) - assert.Equal(t, expectedUri, uri) -} - -func doTestQueryWithError(t *testing.T, ctg ServiceCatalog, resourceUri ResourceUri, outputFormat string, expectedErrorMessage string) { - _, err := ctg.Query(context.TODO(), resourceUri, outputFormat) - assert.ErrorContains(t, err, expectedErrorMessage) -} diff --git a/internal/controller/discovery/knative_catalog.go b/internal/controller/discovery/knative_catalog.go deleted file mode 100644 index be313eac..00000000 --- a/internal/controller/discovery/knative_catalog.go +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - - "k8s.io/client-go/rest" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/log" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - clienteventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" - clientservingv1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1" -) - -const ( - knServiceKind = "services" - knBrokerKind = "brokers" -) - -type knServiceCatalog struct { - dc *KnDiscoveryClient -} - -type KnDiscoveryClient struct { - ServingClient clientservingv1.ServingV1Interface - EventingClient clienteventingv1.EventingV1Interface -} - -func newKnServiceCatalog(discoveryClient *KnDiscoveryClient) knServiceCatalog { - return knServiceCatalog{ - dc: discoveryClient, - } -} - -func newKnServiceCatalogForConfig(cfg *rest.Config) knServiceCatalog { - return knServiceCatalog{ - dc: newKnDiscoveryClientForConfig(cfg), - } -} - -// newKnDiscoveryClientForConfig returns a KnDiscoveryClient discovery client depending on the cluster status, if knative -// serving nor knative eventing are installed, or it was not possible to create that client, returns null. -func newKnDiscoveryClientForConfig(cfg *rest.Config) *KnDiscoveryClient { - var servingClient clientservingv1.ServingV1Interface - var eventingClient clienteventingv1.EventingV1Interface - - if avail, err := knative.GetKnativeAvailability(cfg); err != nil { - klog.V(log.E).ErrorS(err, "Unable to determine if knative is installed in the cluster") - return nil - } else { - if avail.Serving { - if servingClient, err = knative.GetKnativeServingClient(cfg); err != nil { - klog.V(log.E).ErrorS(err, "Unable to get the knative serving client") - return nil - } - } - if avail.Eventing { - if eventingClient, err = knative.GetKnativeEventingClient(cfg); err != nil { - klog.V(log.E).ErrorS(err, "Unable to get the knative eventing client") - return nil - } - } - if servingClient != nil || eventingClient != nil { - return newKnDiscoveryClient(servingClient, eventingClient) - } - } - return nil -} - -func newKnDiscoveryClient(servingClient clientservingv1.ServingV1Interface, eventingClient clienteventingv1.EventingV1Interface) *KnDiscoveryClient { - return &KnDiscoveryClient{ - ServingClient: servingClient, - EventingClient: eventingClient, - } -} - -func (c knServiceCatalog) Query(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if c.dc == nil { - return "", fmt.Errorf("knative KnDiscoveryClient was not provided, maybe knative is not installed in current cluster") - } - switch uri.GVK.Kind { - case knServiceKind: - return c.resolveKnServiceQuery(ctx, uri) - case knBrokerKind: - return c.resolveKnBrokerQuery(ctx, uri) - default: - return "", fmt.Errorf("resolution of knative kind: %s is not implemented", uri.GVK.Kind) - } -} - -func (c knServiceCatalog) resolveKnServiceQuery(ctx context.Context, uri ResourceUri) (string, error) { - if c.dc.ServingClient == nil { - return "", fmt.Errorf("knative ServingClient was not provided, maybe the serving.knative.dev api is not installed in current cluster") - } - if service, err := c.dc.ServingClient.Services(uri.Namespace).Get(ctx, uri.Name, metav1.GetOptions{}); err != nil { - return "", err - } else { - // knative objects discovery should rely on the addressable interface - return service.Status.Address.URL.String(), nil - } -} - -func (c knServiceCatalog) resolveKnBrokerQuery(ctx context.Context, uri ResourceUri) (string, error) { - if c.dc.EventingClient == nil { - return "", fmt.Errorf("knative EventingClient was not provided, maybe the eventing.knative.dev api is not installed in current cluster") - } - if broker, err := c.dc.EventingClient.Brokers(uri.Namespace).Get(ctx, uri.Name, metav1.GetOptions{}); err != nil { - return "", err - } else { - // knative objects discovery should rely on the addressable interface - return broker.Status.Address.URL.String(), nil - } -} diff --git a/internal/controller/discovery/kubernetes_catalog.go b/internal/controller/discovery/kubernetes_catalog.go deleted file mode 100644 index 077adbf7..00000000 --- a/internal/controller/discovery/kubernetes_catalog.go +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - serviceKind = "services" - podKind = "pods" - deploymentKind = "deployments" - statefulSetKind = "statefulsets" - ingressKind = "ingresses" -) - -type k8sServiceCatalog struct { - Client client.Client -} - -func newK8SServiceCatalog(cli client.Client) k8sServiceCatalog { - return k8sServiceCatalog{ - Client: cli, - } -} - -func (c k8sServiceCatalog) Query(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - switch uri.GVK.Kind { - case serviceKind: - return c.resolveServiceQuery(ctx, uri, outputFormat) - case podKind: - return c.resolvePodQuery(ctx, uri, outputFormat) - case deploymentKind: - return c.resolveDeploymentQuery(ctx, uri, outputFormat) - case statefulSetKind: - return c.resolveStatefulSetQuery(ctx, uri, outputFormat) - case ingressKind: - return c.resolveIngressQuery(ctx, uri) - default: - return "", fmt.Errorf("resolution of kubernetes kind: %s is not implemented", uri.GVK.Kind) - } -} - -func (c k8sServiceCatalog) resolveServiceQuery(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if service, err := findService(ctx, c.Client, uri.Namespace, uri.Name); err != nil { - return "", err - } else if serviceUri, err := resolveServiceUri(service, uri.GetPort(), outputFormat); err != nil { - return "", err - } else { - return serviceUri, nil - } -} - -func (c k8sServiceCatalog) resolvePodQuery(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if pod, serviceList, err := findPodAndReferenceServices(ctx, c.Client, uri.Namespace, uri.Name); err != nil { - return "", err - } else { - if serviceList != nil && len(serviceList.Items) > 0 { - referenceService := selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels()) - return resolveServiceUri(referenceService, uri.GetPort(), outputFormat) - } else { - return resolvePodUri(pod, "", uri.GetPort(), outputFormat) - } - } -} - -func (c k8sServiceCatalog) resolveDeploymentQuery(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if deployment, err := findDeployment(ctx, c.Client, uri.Namespace, uri.Name); err != nil { - return "", err - } else { - if serviceList, err := findServicesBySelectorTarget(ctx, c.Client, uri.Namespace, deployment.Spec.Selector.MatchLabels); err != nil { - return "", err - } else if len(serviceList.Items) == 0 { - return "", fmt.Errorf("no service was found for the deployment: %s in namespace: %s", uri.Name, uri.Namespace) - } else { - referenceService := selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels()) - return resolveServiceUri(referenceService, uri.GetPort(), outputFormat) - } - } -} - -func (c k8sServiceCatalog) resolveStatefulSetQuery(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if statefulSet, err := findStatefulSet(ctx, c.Client, uri.Namespace, uri.Name); err != nil { - return "", err - } else { - if serviceList, err := findServicesBySelectorTarget(ctx, c.Client, uri.Namespace, statefulSet.Spec.Selector.MatchLabels); err != nil { - return "", err - } else if len(serviceList.Items) == 0 { - return "", fmt.Errorf("no service was found for the statefulset: %s in namespace: %s", uri.Name, uri.Namespace) - } else { - referenceService := selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels()) - return resolveServiceUri(referenceService, uri.GetPort(), outputFormat) - } - } -} - -func (c k8sServiceCatalog) resolveIngressQuery(ctx context.Context, uri ResourceUri) (string, error) { - if ingress, err := findIngress(ctx, c.Client, uri.Namespace, uri.Name); err != nil { - return "", err - } else { - // for now stick with the first ip or hostname. - loadBalancer := ingress.Status.LoadBalancer.Ingress[0] - var scheme = httpProtocol - var host string - var port = defaultHttpPort - if len(loadBalancer.Hostname) > 0 { - host = loadBalancer.Hostname - } else { - host = loadBalancer.IP - } - // An Ingress does not expose arbitrary ports or protocols other than HTTP and HTTPS - if len(ingress.Spec.TLS) >= 1 { - scheme = httpsProtocol - port = defaultHttpsPort - } - return buildURI(scheme, host, port), nil - } -} diff --git a/internal/controller/discovery/kubernetes_constants.go b/internal/controller/discovery/kubernetes_constants.go deleted file mode 100644 index 78d472d1..00000000 --- a/internal/controller/discovery/kubernetes_constants.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 - -const ( - httpProtocol = "http" - httpsProtocol = "https" - webProtocol = "web" - defaultHttpPort = 80 - defaultHttpsPort = 443 - defaultAppSecurePort = 8443 -) diff --git a/internal/controller/discovery/openshift_catalog.go b/internal/controller/discovery/openshift_catalog.go deleted file mode 100644 index d5c0b561..00000000 --- a/internal/controller/discovery/openshift_catalog.go +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1 "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1" - routev1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/openshift" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - "k8s.io/klog/v2" -) - -const ( - openShiftRoutes = "routes" - openShiftDeploymentConfigs = "deploymentconfigs" -) - -type openShiftServiceCatalog struct { - dc *OpenShiftDiscoveryClient -} - -type OpenShiftDiscoveryClient struct { - Client client.Client - RouteClient routev1.RouteV1Interface - AppsClient appsv1.AppsV1Interface -} - -func newOpenShiftServiceCatalog(discoveryClient *OpenShiftDiscoveryClient) openShiftServiceCatalog { - return openShiftServiceCatalog{ - dc: discoveryClient, - } -} -func newOpenShiftServiceCatalogForClientAndConfig(cli client.Client, cfg *rest.Config) openShiftServiceCatalog { - return openShiftServiceCatalog{ - dc: newOpenShiftDiscoveryClientForClientAndConfig(cli, cfg), - } -} - -func newOpenShiftDiscoveryClientForClientAndConfig(cli client.Client, cfg *rest.Config) *OpenShiftDiscoveryClient { - var routeClient routev1.RouteV1Interface - var appsClient appsv1.AppsV1Interface - var err error - if utils.IsOpenShift() { - if routeClient, err = openshift.GetRouteClient(cfg); err != nil { - klog.V(log.E).ErrorS(err, "Unable to get the openshift route client") - return nil - } - if appsClient, err = openshift.GetAppsClient(cfg); err != nil { - klog.V(log.E).ErrorS(err, "Unable to get the openshift apps client") - return nil - } - return newOpenShiftDiscoveryClient(cli, routeClient, appsClient) - } - return nil -} - -func newOpenShiftDiscoveryClient(cli client.Client, routeClient routev1.RouteV1Interface, appsClient appsv1.AppsV1Interface) *OpenShiftDiscoveryClient { - return &OpenShiftDiscoveryClient{ - Client: cli, - RouteClient: routeClient, - AppsClient: appsClient, - } -} - -func (c openShiftServiceCatalog) Query(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if c.dc == nil { - return "", fmt.Errorf("OpenShiftDiscoveryClient was not provided, maybe current operator is not running in OpenShift") - } - switch uri.GVK.Kind { - case openShiftRoutes: - return c.resolveOpenShiftRouteQuery(ctx, uri) - case openShiftDeploymentConfigs: - return c.resolveOpenShiftDeploymentConfigQuery(ctx, uri, outputFormat) - default: - return "", fmt.Errorf("resolution of openshift kind: %s is not implemented", uri.GVK.Kind) - } -} - -func (c openShiftServiceCatalog) resolveOpenShiftRouteQuery(ctx context.Context, uri ResourceUri) (string, error) { - if route, err := c.dc.RouteClient.Routes(uri.Namespace).Get(ctx, uri.Name, metav1.GetOptions{}); err != nil { - return "", err - } else { - scheme := httpProtocol - if route.Spec.TLS != nil { - scheme = httpsProtocol - } - // the OpenShift routes are only opened at the http/https standard ports. - return fmt.Sprintf("%s://%s", scheme, route.Spec.Host), nil - } -} - -func (c openShiftServiceCatalog) resolveOpenShiftDeploymentConfigQuery(ctx context.Context, uri ResourceUri, outputFormat string) (string, error) { - if deploymentConfig, err := c.dc.AppsClient.DeploymentConfigs(uri.Namespace).Get(ctx, uri.Name, metav1.GetOptions{}); err != nil { - return "", err - } else { - if serviceList, err := findServicesBySelectorTarget(ctx, c.dc.Client, uri.Namespace, deploymentConfig.Spec.Selector); err != nil { - return "", err - } else if len(serviceList.Items) == 0 { - return "", fmt.Errorf("no service was found for the deploymentConfig: %s in namespace: %s", uri.Name, uri.Namespace) - } else { - referenceService := selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels()) - return resolveServiceUri(referenceService, uri.GetPort(), outputFormat) - } - } -} diff --git a/internal/controller/discovery/port_utils.go b/internal/controller/discovery/port_utils.go deleted file mode 100644 index abfd570a..00000000 --- a/internal/controller/discovery/port_utils.go +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -func isSecurePort(port int) bool { - return port == defaultHttpsPort || port == defaultAppSecurePort -} - -// findBestSuitedServicePort returns the best suited ServicePort to connect to a service. -// The optional customPort can be used to determine which port should be used for the communication, when not set, -// the best suited port is returned. For this last, a secure port has precedence over a no-secure port. -func findBestSuitedServicePort(service *corev1.Service, customPort string) *corev1.ServicePort { - // customPort is provided and is configured? - if len(customPort) > 0 { - if result, _ := kubernetes.GetServicePortByName(customPort, service); result != nil { - return result - } - } - // has ssl port? - if result, _ := kubernetes.GetServicePortByName(httpsProtocol, service); result != nil { - return result - } - // has http port? - if result, _ := kubernetes.GetServicePortByName(httpProtocol, service); result != nil { - return result - } - // has web port? - if result, _ := kubernetes.GetServicePortByName(webProtocol, service); result != nil { - return result - } - // by definition a service must always have at least one port, get the first port. - return &service.Spec.Ports[0] -} - -func isSecureServicePort(servicePort *corev1.ServicePort) bool { - return servicePort.Name == httpsProtocol || isSecurePort(int(servicePort.Port)) -} - -// findBestSuitedContainerPort returns the best suited PortPort to connect to a pod, or nil if the pod has no ports at all. -// The optional customPort can be used to determine which port should be used for the communication, when not set, -// the best suited port is returned. For this last, a secure port has precedence over a non-secure port. -func findBestSuitedContainerPort(container *corev1.Container, customPort string) *corev1.ContainerPort { - // containers with no ports are permitted, we must check. - if len(container.Ports) == 0 { - return nil - } - // customPort is provided and configured? - if len(customPort) > 0 { - if result, _ := kubernetes.GetContainerPortByName(customPort, container); result != nil { - return result - } - } - // has ssl port? - if result, _ := kubernetes.GetContainerPortByName(httpsProtocol, container); result != nil { - return result - } - // has http port? - if result, _ := kubernetes.GetContainerPortByName(httpProtocol, container); result != nil { - return result - } - // has web port? - if result, _ := kubernetes.GetContainerPortByName(webProtocol, container); result != nil { - return result - } - // when defined, a ContainerPort must always have containerPort (Required value) - return &container.Ports[0] -} - -func isSecureContainerPort(containerPort *corev1.ContainerPort) bool { - return containerPort.Name == httpsProtocol || isSecurePort(int(containerPort.ContainerPort)) -} diff --git a/internal/controller/discovery/port_utils_test.go b/internal/controller/discovery/port_utils_test.go deleted file mode 100644 index 9e01b9bc..00000000 --- a/internal/controller/discovery/port_utils_test.go +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func TestIsSecurePort(t *testing.T) { - assert.False(t, isSecurePort(80)) - assert.False(t, isSecurePort(8080)) - assert.True(t, isSecurePort(443)) - assert.True(t, isSecurePort(8443)) -} - -func TestBestSuitedServicePort_BestIsCustomPort(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort("not-wanted", tcp, 8282), - mockServicePort(httpsProtocol, tcp, defaultHttpsPort), - mockServicePort(customPortName, tcp, defaultHttpPort)) - doTestBestSuitedServicePort(t, service, customPortName, &service.Spec.Ports[2]) -} - -func TestBestSuitedServicePort_BestIsHttpsPort(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort("not-wanted", tcp, 8282), - mockServicePort(httpProtocol, tcp, defaultHttpPort), - mockServicePort(httpsProtocol, tcp, defaultHttpsPort)) - doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[2]) -} - -func TestBestSuitedServicePort_BestIsHttpPort(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort("not-wanted", tcp, 8282), - mockServicePort(webProtocol, tcp, 81), - mockServicePort(httpProtocol, tcp, defaultHttpPort)) - doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[2]) -} - -func TestBestSuitedServicePort_BestWebPort(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort("not-wanted", tcp, 8282), - mockServicePort(webProtocol, tcp, 81)) - doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[1]) -} - -func TestBestSuitedServicePort_BestIsFirst(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort("first-port", tcp, 8282), - mockServicePort("second-port", tcp, 8383)) - doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[0]) -} - -func TestIsSecureServicePort(t *testing.T) { - servicePort := mockServicePort(httpsProtocol, tcp, 443) - assert.True(t, isSecureServicePort(&servicePort)) - servicePort = mockServicePort("other-secure-port", tcp, 443) - assert.True(t, isSecureServicePort(&servicePort)) - servicePort = mockServicePort(httpProtocol, tcp, 80) - assert.False(t, isSecureServicePort(&servicePort)) -} - -func doTestBestSuitedServicePort(t *testing.T, service *corev1.Service, customPort string, expectedPort *corev1.ServicePort) { - result := findBestSuitedServicePort(service, customPort) - assert.Equal(t, result, expectedPort) -} - -func TestBestSuitedContainerPort_ContainerWithNoPorts(t *testing.T) { - doTestBestSuitedContainerPort(t, mockContainerWithPorts(""), "", nil) -} - -func TestBestSuitedContainerPort_BestIsCustomPort(t *testing.T) { - container := mockContainerWithPorts("", mockContainerPort("not-wanted", tcp, 8282), - mockContainerPort(httpsProtocol, tcp, defaultHttpsPort), - mockContainerPort(customPortName, tcp, defaultHttpPort)) - doTestBestSuitedContainerPort(t, container, customPortName, &container.Ports[2]) -} - -func TestBestSuitedContainerPort_BestIsHttpsPort(t *testing.T) { - container := mockContainerWithPorts("", mockContainerPort("not-wanted", tcp, 8282), - mockContainerPort(httpProtocol, tcp, defaultHttpPort), - mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)) - doTestBestSuitedContainerPort(t, container, "", &container.Ports[2]) -} - -func TestBestSuitedContainerPort_BestIsHttpPort(t *testing.T) { - container := mockContainerWithPorts("", mockContainerPort("not-wanted", tcp, 8282), - mockContainerPort(webProtocol, tcp, 81), - mockContainerPort(httpProtocol, tcp, defaultHttpsPort)) - doTestBestSuitedContainerPort(t, container, "", &container.Ports[2]) -} - -func TestBestSuitedContainerPort_BestWebPort(t *testing.T) { - container := mockContainerWithPorts("", mockContainerPort("not-wanted", tcp, 8282), - mockContainerPort(webProtocol, tcp, 81)) - doTestBestSuitedContainerPort(t, container, "", &container.Ports[1]) -} - -func TestBestSuitedContainerPort_BestIsFirst(t *testing.T) { - container := mockContainerWithPorts("", mockContainerPort("first-port", tcp, 8282), - mockContainerPort("second-port", tcp, 8383)) - doTestBestSuitedContainerPort(t, container, "", &container.Ports[0]) -} - -func doTestBestSuitedContainerPort(t *testing.T, container *corev1.Container, customPort string, expectedPort *corev1.ContainerPort) { - result := findBestSuitedContainerPort(container, customPort) - assert.Equal(t, result, expectedPort) -} - -func TestIsSecureContainerPort(t *testing.T) { - containerPort := mockContainerPort(httpsProtocol, tcp, 443) - assert.True(t, isSecureContainerPort(&containerPort)) - containerPort = mockContainerPort("other-secure-port", tcp, 443) - assert.True(t, isSecureContainerPort(&containerPort)) - containerPort = mockContainerPort(httpProtocol, tcp, 80) - assert.False(t, isSecureContainerPort(&containerPort)) -} diff --git a/internal/controller/discovery/queries.go b/internal/controller/discovery/queries.go deleted file mode 100644 index 37a7e1a6..00000000 --- a/internal/controller/discovery/queries.go +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - networkingV1 "k8s.io/api/networking/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -// findService finds a service by name in the given namespace. -func findService(ctx context.Context, cli client.Client, namespace string, name string) (*corev1.Service, error) { - service := &corev1.Service{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, service); err != nil { - return nil, err - } - return service, nil -} - -// findServicesBySelectorTarget finds the services for which all the configured selector labels are present in the -// selection target map. -func findServicesBySelectorTarget(ctx context.Context, cli client.Client, namespace string, selectorTarget map[string]string) (*corev1.ServiceList, error) { - serviceList := &corev1.ServiceList{} - items := make([]corev1.Service, 0) - if err := cli.List(ctx, serviceList, client.InNamespace(namespace)); err != nil { - return nil, err - } else { - for _, service := range serviceList.Items { - if len(service.Spec.Selector) > 0 && containsSubset(selectorTarget, service.Spec.Selector) { - items = append(items, service) - } - } - } - return &corev1.ServiceList{Items: items}, nil -} - -// selectBestSuitedServiceByCustomLabels In situations where a previous query returned many Services, for example, to -// access a set of pods, or a deployment, we can filter them by a set of customLabels, to determine which one is the best suited. -func selectBestSuitedServiceByCustomLabels(serviceList *corev1.ServiceList, customLabels map[string]string) *corev1.Service { - var filteredService *corev1.Service = nil - if len(serviceList.Items) > 0 { - if len(serviceList.Items) == 1 { - filteredService = &serviceList.Items[0] - } else { - filteredService = &serviceList.Items[0] - if len(customLabels) > 0 { - if filteredServiceList := filterServiceListByLabelsSubset(serviceList, customLabels); len(filteredServiceList.Items) > 0 { - filteredService = &filteredServiceList.Items[0] - } - } - } - } - return filteredService -} - -func filterServiceListByLabelsSubset(serviceList *corev1.ServiceList, labels map[string]string) *corev1.ServiceList { - var items = make([]corev1.Service, 0) - for _, service := range serviceList.Items { - if containsSubset(service.Labels, labels) { - items = append(items, service) - } - } - return &corev1.ServiceList{Items: items} -} - -func containsSubset(container map[string]string, subset map[string]string) bool { - if container == nil { - return subset == nil - } else if subset == nil { - return true - } else { - for k, v := range subset { - if cv := container[k]; cv != v { - return false - } - } - } - return true -} - -// findPod finds a pod by name in the given namespace. -func findPod(ctx context.Context, cli client.Client, namespace string, name string) (*corev1.Pod, error) { - pod := &corev1.Pod{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, pod); err != nil { - return nil, err - } - return pod, nil -} - -// findPodAndReferenceServices finds a pod by name in the given namespace, at the same time it piggybacks potential -// reference services if any. The reference services are determined by looking if the corresponding selector labels -// matches the pod labels. -func findPodAndReferenceServices(ctx context.Context, cli client.Client, namespace string, name string) (*corev1.Pod, *corev1.ServiceList, error) { - if pod, err := findPod(ctx, cli, namespace, name); err != nil { - return nil, nil, err - } else { - if len(pod.Labels) > 0 { - if serviceList, err := findServicesBySelectorTarget(ctx, cli, namespace, pod.Labels); err != nil { - return nil, nil, err - } else if len(serviceList.Items) > 0 { - return pod, serviceList, nil - } - } - return pod, nil, nil - } -} - -// findDeployment finds a deployment by name in the given namespace. -func findDeployment(ctx context.Context, cli client.Client, namespace string, name string) (*appsv1.Deployment, error) { - deployment := &appsv1.Deployment{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, deployment); err != nil { - return nil, err - } - return deployment, nil -} - -// findStatefulSet finds a stateful set by name in the given namespace. -func findStatefulSet(ctx context.Context, cli client.Client, namespace string, name string) (*appsv1.StatefulSet, error) { - statefulSet := &appsv1.StatefulSet{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, statefulSet); err != nil { - return nil, err - } - return statefulSet, nil -} - -// findIngress finds an ingress by name in the given namespace. -func findIngress(ctx context.Context, cli client.Client, namespace string, name string) (*networkingV1.Ingress, error) { - ingress := &networkingV1.Ingress{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, ingress); err != nil { - return nil, err - } - return ingress, nil -} diff --git a/internal/controller/discovery/queries_test.go b/internal/controller/discovery/queries_test.go deleted file mode 100644 index b0500b78..00000000 --- a/internal/controller/discovery/queries_test.go +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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" - "testing" - - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - networkingV1 "k8s.io/api/networking/v1" - "sigs.k8s.io/controller-runtime/pkg/client/fake" -) - -func Test_findService(t *testing.T) { - service := mockService1(nil) - cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build() - result, err := findService(context.TODO(), cli, namespace1, service1Name) - - assert.NoError(t, err) - assert.Equal(t, service, result) -} - -func Test_findServiceNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - _, err := findService(context.TODO(), cli, namespace1, service1Name) - assert.ErrorContains(t, err, "\"service1Name\" not found") -} - -func Test_findServicesBySelectorTarget(t *testing.T) { - selector1Labels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - selector2Labels := &map[string]string{ - label1: valueLabel1, - label3: valueLabel3, - } - selector3Labels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - - service1 := mockService1(selector1Labels) - service2 := mockService2(selector2Labels) - service3 := mockService3(selector3Labels) - cli := fake.NewClientBuilder().WithRuntimeObjects(service1, service2, service3).Build() - serviceList, err := findServicesBySelectorTarget(context.TODO(), cli, namespace1, *selector1Labels) - - assert.NoError(t, err) - assert.Len(t, serviceList.Items, 2) - assert.Equal(t, service1, &serviceList.Items[0]) - assert.Equal(t, service3, &serviceList.Items[1]) -} - -func Test_findServicesBySelectorTargetNotFound(t *testing.T) { - selectorLabels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - queryLabels := map[string]string{ - label1: valueLabel1, - } - service := mockService1(selectorLabels) - cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build() - serviceList, err := findServicesBySelectorTarget(context.TODO(), cli, namespace1, queryLabels) - - assert.NoError(t, err) - assert.Len(t, serviceList.Items, 0) -} - -func Test_selectBestSuitedServiceByCustomLabels(t *testing.T) { - service1 := mockService1(nil) - service1.Labels = map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - service2 := mockService2(nil) - service2.Labels = map[string]string{ - label1: valueLabel1, - label3: valueLabel3, - "environment": "dev", - } - service3 := mockService2(nil) - service3.Labels = map[string]string{ - label2: valueLabel2, - label3: valueLabel3, - } - serviceList := &corev1.ServiceList{ - Items: []corev1.Service{*service1, *service2, *service3}, - } - bestSuitedService := selectBestSuitedServiceByCustomLabels(serviceList, map[string]string{"environment": "dev"}) - assert.Equal(t, service2, bestSuitedService) -} - -func Test_filterServiceListByLabelsSubset(t *testing.T) { - service1 := mockService1(nil) - service1.Labels = map[string]string{ - label1: valueLabel1, - } - service2 := mockService2(nil) - service2.Labels = map[string]string{ - label1: valueLabel1, - label3: valueLabel3, - } - service3 := mockService3(nil) - service3.Labels = map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - label3: valueLabel3, - } - serviceList := &corev1.ServiceList{ - Items: []corev1.Service{*service1, *service2, *service3}, - } - filteredServiceList := filterServiceListByLabelsSubset(serviceList, map[string]string{ - label1: valueLabel1, - label3: valueLabel3}) - - assert.Len(t, filteredServiceList.Items, 2) - assert.Equal(t, *service2, filteredServiceList.Items[0]) - assert.Equal(t, *service3, filteredServiceList.Items[1]) -} - -func Test_findPod(t *testing.T) { - pod := mockPod1(nil) - cli := fake.NewClientBuilder().WithRuntimeObjects(pod).Build() - result, err := findPod(context.TODO(), cli, namespace1, pod1Name) - - assert.NoError(t, err) - assert.Equal(t, pod, result) -} - -func Test_findPodNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - _, err := findPod(context.TODO(), cli, namespace1, pod1Name) - assert.ErrorContains(t, err, "\"pod1Name\" not found") -} - -func Test_findPodAndReferenceServicesWithReferenceService(t *testing.T) { - podLabels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - label3: valueLabel3, - } - selectorLabels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - service := mockService1(selectorLabels) - pod := mockPod1(podLabels) - cli := fake.NewClientBuilder().WithRuntimeObjects(service, pod).Build() - resultPod, referenceServices, err := findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name) - assert.NoError(t, err) - assert.Equal(t, pod, resultPod) - assert.Len(t, referenceServices.Items, 1) - assert.Equal(t, *service, referenceServices.Items[0]) -} - -func Test_findPodAndReferenceServicesWithoutReferenceService(t *testing.T) { - podLabels := &map[string]string{ - label1: valueLabel1, - } - selectorLabels := &map[string]string{ - label1: valueLabel1, - label2: valueLabel2, - } - service := mockService1(selectorLabels) - pod := mockPod1(podLabels) - cli := fake.NewClientBuilder().WithRuntimeObjects(service, pod).Build() - resultPod, referenceServices, err := findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name) - assert.NoError(t, err) - assert.Equal(t, pod, resultPod) - assert.Nil(t, referenceServices) -} - -func Test_findPodAndReferenceServicesNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - resultPod, resultService, err := findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name) - assert.ErrorContains(t, err, "\"pod1Name\" not found") - assert.Nil(t, resultPod) - assert.Nil(t, resultService) -} - -func Test_findDeployment(t *testing.T) { - deployment := mockDeployment1(nil) - cli := fake.NewClientBuilder().WithRuntimeObjects(deployment).Build() - result, err := findDeployment(context.TODO(), cli, namespace1, deployment1Name) - - assert.NoError(t, err) - assert.Equal(t, deployment, result) -} - -func Test_findDeploymentNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - _, err := findDeployment(context.TODO(), cli, namespace1, deployment1Name) - assert.ErrorContains(t, err, "\"deployment1Name\" not found") -} - -func Test_findStatefulSet(t *testing.T) { - statefulSet := mockStatefulSet1() - cli := fake.NewClientBuilder().WithRuntimeObjects(statefulSet).Build() - result, err := findStatefulSet(context.TODO(), cli, namespace1, statefulSet1Name) - - assert.NoError(t, err) - assert.Equal(t, statefulSet, result) -} - -func Test_findStatefulSetNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - _, err := findStatefulSet(context.TODO(), cli, namespace1, statefulSet1Name) - assert.ErrorContains(t, err, "\"statefulSet1Name\" not found") -} - -func Test_findIngress(t *testing.T) { - ingress := mockIngress1() - cli := fake.NewClientBuilder().WithRuntimeObjects(ingress).Build() - result, err := findIngress(context.TODO(), cli, namespace1, ingress1Name) - - assert.NoError(t, err) - assert.Equal(t, ingress, result) -} - -func Test_findIngressNotFound(t *testing.T) { - cli := fake.NewClientBuilder().Build() - _, err := findIngress(context.TODO(), cli, namespace1, ingress1Name) - assert.ErrorContains(t, err, "\"ingress1Name\" not found") -} - -func mockService1(selectorLabels *map[string]string) *corev1.Service { - return mockService(namespace1, service1Name, nil, selectorLabels) -} - -func mockService2(selectorLabels *map[string]string) *corev1.Service { - return mockService(namespace1, service2Name, nil, selectorLabels) -} - -func mockService3(selectorLabels *map[string]string) *corev1.Service { - return mockService(namespace1, service3Name, nil, selectorLabels) -} - -func mockPod1(labels *map[string]string) *corev1.Pod { - return mockPod(namespace1, pod1Name, labels) -} - -func mockPod2(labels *map[string]string) *corev1.Pod { - return mockPod(namespace1, pod2Name, labels) -} - -func mockPod3(labels *map[string]string) *corev1.Pod { - return mockPod(namespace1, pod3Name, labels) -} - -func mockDeployment1(labels *map[string]string) *appsv1.Deployment { - return mockDeployment(namespace1, deployment1Name, labels, nil) -} - -func mockStatefulSet1() *appsv1.StatefulSet { - return mockStatefulSet(namespace1, statefulSet1Name, nil, nil) -} - -func mockIngress1() *networkingV1.Ingress { - return mockIngress(namespace1, ingress1Name) -} diff --git a/internal/controller/discovery/test_utils.go b/internal/controller/discovery/test_utils.go deleted file mode 100644 index c05fea11..00000000 --- a/internal/controller/discovery/test_utils.go +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "fmt" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - networkingV1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -const ( - namespace1 = "namespace1" - service1Name = "service1Name" - service2Name = "service2Name" - service3Name = "service3Name" - deployment1Name = "deployment1Name" - statefulSet1Name = "statefulSet1Name" - pod1Name = "pod1Name" - pod2Name = "pod2Name" - pod3Name = "pod3Name" - container1Name = "container1Name" - container2Name = "container2Name" - ingress1Name = "ingress1Name" - label1 = "label1" - valueLabel1 = "valueLabel1" - label2 = "label2" - valueLabel2 = "valueLabel2" - label3 = "label3" - valueLabel3 = "valueLabel3" - customPortName = "my-custom-port" - tcp = "TCP" - uidOwner1 = "uidOwner1" - uidOwner2 = "uidOwner2" - replicaSet1Name = "replicaSet1Name" - replicaSet2Name = "replicaSet2Name" - replicaSet3Name = "replicaSet3Name" - - knServiceName1 = "knServiceName1" - knBrokerName1 = "knBrokerName1" - - openShiftRouteName1 = "openShiftRouteName1" - openShiftRouteHost1 = "openshiftroutehost1" - - openShiftDeploymentConfigName1 = "openShiftDeploymentConfigName1" -) - -func mockService(namespace string, name string, labels *map[string]string, selectorLabels *map[string]string) *corev1.Service { - service := &corev1.Service{ - TypeMeta: metav1.TypeMeta{ - Kind: "Service", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - } - if labels != nil { - service.ObjectMeta.Labels = *labels - } - if selectorLabels != nil { - service.Spec.Selector = *selectorLabels - } - return service -} - -func mockServiceWithPorts(namespace string, name string, ports ...corev1.ServicePort) *corev1.Service { - service := mockService(namespace, name, &map[string]string{}, nil) - service.Spec.Ports = ports - return service -} - -func mockServicePort(name string, protocol string, port int32) corev1.ServicePort { - return corev1.ServicePort{ - Name: name, - Protocol: corev1.Protocol(protocol), - Port: port, - } -} - -func mockPod(namespace string, name string, labels *map[string]string) *corev1.Pod { - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - } - if labels != nil { - pod.ObjectMeta.Labels = *labels - } - return pod -} - -func mockPodWithContainers(namespace string, name string, containers ...corev1.Container) *corev1.Pod { - pod := mockPod(namespace, name, &map[string]string{}) - pod.Spec.Containers = containers - return pod -} - -func mockContainerWithPorts(name string, ports ...corev1.ContainerPort) *corev1.Container { - return &corev1.Container{ - Name: name, - Ports: ports, - } -} - -func mockContainerPort(name string, protocol string, port int32) corev1.ContainerPort { - return corev1.ContainerPort{ - Name: name, - HostPort: 0, - ContainerPort: port, - Protocol: corev1.Protocol(protocol), - } -} - -func mockReplicaSet(namespace string, name string, ownerReferenceUID string) *appsv1.ReplicaSet { - replicaSet := &appsv1.ReplicaSet{ - TypeMeta: metav1.TypeMeta{ - Kind: "ReplicaSet", - APIVersion: "apps/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - OwnerReferences: []metav1.OwnerReference{{UID: types.UID(ownerReferenceUID)}}, - UID: types.UID(fmt.Sprintf("%s-%s-mock-replicaset-uid", namespace, name)), - }, - } - return replicaSet -} - -func mockDeployment(namespace string, name string, labels *map[string]string, selector *map[string]string) *appsv1.Deployment { - deployment := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: "apps/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - UID: types.UID(fmt.Sprintf("%s-%s-mock-deployment-uid", namespace, name)), - }, - } - if labels != nil { - deployment.ObjectMeta.Labels = *labels - } - if selector != nil { - deployment.Spec.Selector = &metav1.LabelSelector{MatchLabels: *selector} - } - return deployment -} - -func mockStatefulSet(namespace string, name string, labels *map[string]string, selector *map[string]string) *appsv1.StatefulSet { - statefulSet := &appsv1.StatefulSet{ - TypeMeta: metav1.TypeMeta{ - Kind: "StatefulSet", - APIVersion: "apps/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - UID: types.UID(fmt.Sprintf("%s-%s-mock-statefulset-uid", namespace, name)), - }, - } - if labels != nil { - statefulSet.ObjectMeta.Labels = *labels - } - if selector != nil { - statefulSet.Spec.Selector = &metav1.LabelSelector{MatchLabels: *selector} - } - return statefulSet -} - -func mockIngress(namespace string, name string) *networkingV1.Ingress { - ingress := &networkingV1.Ingress{ - TypeMeta: metav1.TypeMeta{ - Kind: "Ingress", - APIVersion: "networking.k8s.io/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - } - return ingress -} diff --git a/internal/controller/discovery/uri_parser.go b/internal/controller/discovery/uri_parser.go deleted file mode 100644 index 09f9aec0..00000000 --- a/internal/controller/discovery/uri_parser.go +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "fmt" - "regexp" - "strings" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - // valid namespace, name, or label name. - dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" - queryParamName = "[a-zA-Z0-9][-a-zAz0-9]*" - queryParamValue = "[/a-zA-Z0-9][/-a-zAz0-9]*" - - namespaceAndNamePattern = "^/((" + dns1123LabelFmt + ")+)(/(" + dns1123LabelFmt + ")+)?" - queryStringPattern = "^(\\?((" + queryParamName + ")+\\=(" + queryParamValue + ")+)" + - "(&(" + queryParamName + ")+\\=(" + queryParamValue + ")+)*)?$" - - kubernetesGroupsPattern = "^(" + kubernetesServices + - "|" + kubernetesPods + - "|" + kubernetesDeployments + - "|" + kubernetesStatefulSets + - "|" + kubernetesIngresses + ")" - - knativeGroupsPattern = "^(" + knativeServices + "|" + knativeBrokers + ")" - - knativeSimplifiedServicePatten = "knative:" + "(" + dns1123LabelFmt + ")" + "(/(" + dns1123LabelFmt + ")+)?" - - openshiftGroupsPattern = "^(" + openshiftDeploymentConfigs + - "|" + openshiftRoutes + ")" -) - -var kubernetesGroupsExpr = regexp.MustCompile(kubernetesGroupsPattern) -var knativeGroupsExpr = regexp.MustCompile(knativeGroupsPattern) -var knativeSimplifiedServiceExpr = regexp.MustCompile(knativeSimplifiedServicePatten) -var openshiftGroupsExpr = regexp.MustCompile(openshiftGroupsPattern) -var namespaceAndNameExpr = regexp.MustCompile(namespaceAndNamePattern) -var queryStringExpr = regexp.MustCompile(queryStringPattern) - -func ParseUri(uri string) (*ResourceUri, error) { - if split := kubernetesGroupsExpr.Split(uri, -1); len(split) == 2 { - return parseKubernetesUri(uri, kubernetesGroupsExpr.FindString(uri), split[1]) - } else if split := knativeGroupsExpr.Split(uri, -1); len(split) == 2 { - return parseKnativeUri(uri, knativeGroupsExpr.FindString(uri), split[1]) - } else if knativeSimplifiedServiceExpr.MatchString(uri) { - return parseKnativeSimplifiedServiceUri(uri) - } else if split := openshiftGroupsExpr.Split(uri, -1); len(split) == 2 { - return parseOpenshiftUri(uri, openshiftGroupsExpr.FindString(uri), split[1]) - } - return nil, fmt.Errorf("invalid uri: %s, not correspond to any of the available schemes format: %s, %s, %s", uri, KubernetesScheme, KnativeScheme, OpenshiftScheme) -} - -func parseKubernetesUri(uri string, schemaAndGroup string, after string) (*ResourceUri, error) { - if namespace, name, gvk, queryParams, err := parseNamespaceNameGVKAndQueryParams(uri, schemaAndGroup, after); err != nil { - return nil, err - } else { - return &ResourceUri{ - Scheme: KubernetesScheme, - GVK: *gvk, - Namespace: namespace, - Name: name, - QueryParams: queryParams, - }, nil - } -} - -func parseNamespaceNameGVKAndQueryParams(uri string, schemaAndGroup string, after string) (namespace string, name string, gvk *v1.GroupVersionKind, queryParams map[string]string, err error) { - if split := namespaceAndNameExpr.Split(after, -1); len(split) == 2 { - namespaceAndName := namespaceAndNameExpr.FindString(after) - namespaceAndNameSplit := strings.Split(namespaceAndName, "/") - if len(namespaceAndNameSplit) == 3 { - namespace = namespaceAndNameSplit[1] - name = namespaceAndNameSplit[2] - } else { - name = namespaceAndNameSplit[1] - } - var queryParams map[string]string - var err error - if queryParams, err = parseQueryParams(uri, split[1]); err != nil { - return "", "", nil, queryParams, err - } - if gvk, err = parseGVK(schemaAndGroup); err != nil { - return "", "", nil, queryParams, err - } else { - return namespace, name, gvk, queryParams, nil - } - } else { - return "", "", nil, queryParams, fmt.Errorf("invalid %s service uri: %s, provided namespace, name, or query parameters %s not correspond "+ - "to the expected formats: /my-namespace/my-service?label-name=label-value&another-label=another-value", schemaAndGroup, uri, after) - } -} -func parseQueryParams(uri string, queryParams string) (map[string]string, error) { - result := make(map[string]string) - if len(queryParams) > 0 { - if !queryStringExpr.MatchString(queryParams) { - return nil, fmt.Errorf("invalid uri: %s, provided query string: %s not correspond to the expeced format: ?label-name=label-value&another-label=another-value", uri, queryParams) - } else { - queryParamsTerms := strings.Split(queryParams[1:], "&") - for _, term := range queryParamsTerms { - termSplit := strings.Split(term, "=") - result[termSplit[0]] = termSplit[1] - } - } - } - return result, nil -} - -func parseGVK(schemaGvk string) (*v1.GroupVersionKind, error) { - switch schemaGvk { - case kubernetesServices: - return &v1.GroupVersionKind{ - Version: "v1", - Kind: "services", - }, nil - case kubernetesPods: - return &v1.GroupVersionKind{ - Version: "v1", - Kind: "pods", - }, nil - case kubernetesDeployments: - return &v1.GroupVersionKind{ - Group: "apps", - Version: "v1", - Kind: "deployments", - }, nil - case kubernetesStatefulSets: - return &v1.GroupVersionKind{ - Group: "apps", - Version: "v1", - Kind: "statefulsets", - }, nil - case kubernetesIngresses: - return &v1.GroupVersionKind{ - Group: "networking.k8s.io", - Version: "v1", - Kind: "ingresses", - }, nil - case knativeServices: - return &v1.GroupVersionKind{ - Group: "serving.knative.dev", - Version: "v1", - Kind: "services", - }, nil - case knativeBrokers: - return &v1.GroupVersionKind{ - Group: "eventing.knative.dev", - Version: "v1", - Kind: "brokers", - }, nil - case openshiftRoutes: - return &v1.GroupVersionKind{ - Group: "route.openshift.io", - Version: "v1", - Kind: "routes", - }, nil - case openshiftDeploymentConfigs: - return &v1.GroupVersionKind{ - Group: "apps.openshift.io", - Version: "v1", - Kind: "deploymentconfigs", - }, nil - default: - return nil, fmt.Errorf("unknown schema and gvk: %s", schemaGvk) - } -} - -func parseKnativeUri(uri string, schemaAndGroup string, after string) (*ResourceUri, error) { - if namespace, name, gvk, queryParams, err := parseNamespaceNameGVKAndQueryParams(uri, schemaAndGroup, after); err != nil { - return nil, err - } else { - return &ResourceUri{ - Scheme: KnativeScheme, - GVK: *gvk, - Namespace: namespace, - Name: name, - QueryParams: queryParams, - }, nil - } -} - -func parseKnativeSimplifiedServiceUri(uri string) (*ResourceUri, error) { - if !strings.HasPrefix(uri, "knative:") { - return nil, fmt.Errorf("invalid knative simplified service uri: %s", uri) - } else { - nameAndNamespace := uri[len("knative:"):] - var name, namespace string - namespaceAndNameSplit := strings.Split(nameAndNamespace, "/") - if len(namespaceAndNameSplit) == 2 { - namespace = namespaceAndNameSplit[0] - name = namespaceAndNameSplit[1] - } else { - name = namespaceAndNameSplit[0] - } - - return &ResourceUri{ - Scheme: KnativeScheme, - GVK: v1.GroupVersionKind{ - Group: "serving.knative.dev", - Version: "v1", - Kind: "services", - }, - Namespace: namespace, - Name: name, - QueryParams: map[string]string{}, - }, nil - } -} - -func parseOpenshiftUri(uri string, schemaAndGroup string, after string) (*ResourceUri, error) { - if namespace, name, gvk, queryParams, err := parseNamespaceNameGVKAndQueryParams(uri, schemaAndGroup, after); err != nil { - return nil, err - } else { - return &ResourceUri{ - Scheme: OpenshiftScheme, - GVK: *gvk, - Namespace: namespace, - Name: name, - QueryParams: queryParams, - }, nil - } -} diff --git a/internal/controller/discovery/uri_parser_test.go b/internal/controller/discovery/uri_parser_test.go deleted file mode 100644 index 4b80e3ca..00000000 --- a/internal/controller/discovery/uri_parser_test.go +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var KubernetesServicesTestValues = map[string]*ResourceUri{ - "kubernetes:services.v1": nil, - - "kubernetes:services.v1/": nil, - - "kubernetes:services.v1/my-service": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Name("my-service").Build(), - - "kubernetes:services.v1/my-service?": nil, - - "kubernetes:services.v1/my-service?label-a": nil, - - "kubernetes:services.v1/my-service?label-a=": nil, - - "kubernetes:services.v1/my-service?label-a=value-a": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Name("my-service"). - WithQueryParam("label-a", "value-a").Build(), - - "kubernetes:services.v1/my-service?label-a=value-a&": nil, - - "kubernetes:services.v1/my-service?label-a=value-a&label-b": nil, - - "kubernetes:services.v1/my-service?label-a=value-a&label-b=": nil, - - "kubernetes:services.v1/my-service?label-a=value-a&label-b=value-b": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Name("my-service"). - WithQueryParam("label-a", "value-a"). - WithQueryParam("label-b", "value-b").Build(), - - "kubernetes:services.v1/my-namespace/": nil, - - "kubernetes:services.v1/my-namespace/my-service": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Namespace("my-namespace"). - Name("my-service"). - Build(), - - "kubernetes:services.v1/my-namespace/my-service/": nil, - - "kubernetes:services.v1/my-namespace/my-service/another": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a=": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a=value-a": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Namespace("my-namespace"). - Name("my-service"). - WithQueryParam("label-a", "value-a").Build(), - - "kubernetes:services.v1/my-namespace/my-service?label-a=value-a&": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b=": nil, - - "kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b=value-b&port=custom-port-value": NewResourceUriBuilder(KubernetesScheme). - Kind("services"). - Version("v1"). - Namespace("my-namespace"). - Name("my-service"). - WithQueryParam("label-a", "value-a"). - WithQueryParam("label-b", "value-b"). - WithPort("custom-port-value").Build(), -} - -var KnativeServicesTestValues = map[string]*ResourceUri{ - "knative:/": nil, - - "knative:my-service": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Name("my-service").Build(), - - "knative:my-namespace/my-service": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Namespace("my-namespace"). - Name("my-service").Build(), - - "knative:services.v1.serving.knative.dev": nil, - - "knative:services.v1.serving.knative.dev/": nil, - - "knative:services.v1.serving.knative.dev/my-service": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Name("my-service").Build(), - - "knative:services.v1.serving.knative.dev/my-service?": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a=": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a=value-a": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Name("my-service"). - WithQueryParam("label-a", "value-a").Build(), - - "knative:services.v1.serving.knative.dev/my-service?label-a=value-a&": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a=value-a&label-b": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a=value-a&label-b=": nil, - - "knative:services.v1.serving.knative.dev/my-service?label-a=value-a&label-b=value-b": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Group("serving.knative.dev"). - Version("v1"). - Name("my-service"). - WithQueryParam("label-a", "value-a"). - WithQueryParam("label-b", "value-b").Build(), - - "knative:services.v1.serving.knative.dev/my-namespace/": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Group("serving.knative.dev"). - Version("v1"). - Namespace("my-namespace"). - Name("my-service"). - Build(), - - "knative:services.v1.serving.knative.dev/my-namespace/my-service/": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service/another": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=value-a": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Namespace("my-namespace"). - Name("my-service"). - WithQueryParam("label-a", "value-a").Build(), - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=value-a&": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=value-a&label-b": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=value-a&label-b=": nil, - - "knative:services.v1.serving.knative.dev/my-namespace/my-service?label-a=value-a&label-b=value-b&port=custom-port-value": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Namespace("my-namespace"). - Name("my-service"). - WithQueryParam("label-a", "value-a"). - WithQueryParam("label-b", "value-b"). - WithPort("custom-port-value").Build(), - - "knative:services.v1.serving.knative.dev/my-namespace/my-function?path=/myKnativeFunction": NewResourceUriBuilder(KnativeScheme). - Kind("services"). - Version("v1"). - Group("serving.knative.dev"). - Namespace("my-namespace"). - Name("my-function"). - WithQueryParam("path", "/myKnativeFunction").Build(), -} - -var KnativeBrokersTestValues = map[string]*ResourceUri{ - "knative:/": nil, - - "knative:brokers.v1.eventing.knative.dev": nil, - - "knative:brokers.v1.eventing.knative.dev/": nil, - - "knative:brokers.v1.eventing.knative.dev/my-broker": NewResourceUriBuilder(KnativeScheme). - Kind("brokers"). - Version("v1"). - Group("eventing.knative.dev"). - Name("my-broker").Build(), - - "knative:brokers.v1.eventing.knative.dev/my-namespace/": nil, - - "knative:brokers.v1.eventing.knative.dev/my-namespace/my-broker": NewResourceUriBuilder(KnativeScheme). - Kind("brokers"). - Group("eventing.knative.dev"). - Version("v1"). - Namespace("my-namespace"). - Name("my-broker"). - Build(), - - "knative:brokers.v1.eventing.knative.dev/my-namespace/my-broker/": nil, - - "knative:brokers.v1.eventing.knative.dev/my-namespace/my-broker/another": nil, -} - -var OpenshiftRoutesTestValues = map[string]*ResourceUri{ - "openshift:routes.v1.route.openshift.io": nil, - - "openshift:routes.v1.route.openshift.io/my-route": NewResourceUriBuilder(OpenshiftScheme). - Kind("routes"). - Group("route.openshift.io"). - Version("v1"). - Name("my-route"). - Build(), - - "openshift:routes.v1.route.openshift.io/my-namespace/my-route": NewResourceUriBuilder(OpenshiftScheme). - Kind("routes"). - Group("route.openshift.io"). - Version("v1"). - Namespace("my-namespace"). - Name("my-route"). - Build(), -} - -var OpenshiftDeploymentConfigsTestValues = map[string]*ResourceUri{ - "openshift:deploymentconfigs.v1.apps.openshift.io": nil, - - "openshift:deploymentconfigs.v1.apps.openshift.io/my-deployment-config": NewResourceUriBuilder(OpenshiftScheme). - Kind("deploymentconfigs"). - Group("apps.openshift.io"). - Version("v1"). - Name("my-deployment-config"). - Build(), - - "openshift:deploymentconfigs.v1.apps.openshift.io/my-namespace/my-deployment-config": NewResourceUriBuilder(OpenshiftScheme). - Kind("deploymentconfigs"). - Group("apps.openshift.io"). - Version("v1"). - Namespace("my-namespace"). - Name("my-deployment-config"). - Build(), -} - -func TestParseKubernetesServicesURI(t *testing.T) { - for k, v := range KubernetesServicesTestValues { - doTestParseURI(t, k, v) - } -} - -func TestParseKnativeServicesURI(t *testing.T) { - for k, v := range KnativeServicesTestValues { - doTestParseURI(t, k, v) - } -} - -func TestParseKnativeBrokersURI(t *testing.T) { - for k, v := range KnativeBrokersTestValues { - doTestParseURI(t, k, v) - } -} - -func TestParseOpenshiftRoutesURI(t *testing.T) { - for k, v := range OpenshiftRoutesTestValues { - doTestParseURI(t, k, v) - } -} - -func TestParseOpenshiftDeploymentConfigsURI(t *testing.T) { - for k, v := range OpenshiftDeploymentConfigsTestValues { - doTestParseURI(t, k, v) - } -} - -func doTestParseURI(t *testing.T, url string, expectedUri *ResourceUri) { - result, err := ParseUri(url) - if expectedUri == nil { - if result != nil { - assert.Nil(t, result, "parsing of url: %s should have failed, but returned: %s", url, result.String()) - } - assert.Error(t, err, "parsing of url: %s should have failed", url) - } else { - assertEquals(t, result, expectedUri) - } -} - -func assertEquals(t *testing.T, uri *ResourceUri, expectedUri *ResourceUri) { - assert.NotNil(t, uri, "uri can not be nil") - assert.NotNil(t, expectedUri, "expectedUri can not be nil") - assert.Equal(t, uri.Scheme, expectedUri.Scheme) - assert.Equal(t, uri.Namespace, expectedUri.Namespace) - assert.Equal(t, uri.Name, expectedUri.Name) - assert.Equal(t, uri.GetPort(), expectedUri.GetPort()) - assert.Equal(t, uri.GVK.Group, expectedUri.GVK.Group) - assert.Equal(t, uri.GVK.Version, expectedUri.GVK.Version) - assert.Equal(t, uri.GVK.Kind, expectedUri.GVK.Kind) - assert.Equal(t, len(uri.QueryParams), len(expectedUri.QueryParams)) - for k, v := range uri.QueryParams { - assert.True(t, len(expectedUri.QueryParams[k]) > 0, "label %s is not present in expectedUri: %s", k, expectedUri.String()) - assert.Equal(t, v, expectedUri.QueryParams[k], "value for label %s in expectedUri should be %s, but is %s", k, v, expectedUri.QueryParams[k]) - } -} diff --git a/internal/controller/discovery/uri_utils.go b/internal/controller/discovery/uri_utils.go deleted file mode 100644 index 20feeb6f..00000000 --- a/internal/controller/discovery/uri_utils.go +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "fmt" - "strings" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -func resolveServiceUri(service *corev1.Service, customPort string, outputFormat string) (string, error) { - var port int - var protocol string - var host string - var err error = nil - - switch service.Spec.Type { - case corev1.ServiceTypeExternalName: - // ExternalName may not work properly with SSL: - // https://kubernetes.io/docs/concepts/services-networking/service/#externalname - protocol = httpProtocol - host = service.Spec.ExternalName - port = 80 - case corev1.ServiceTypeClusterIP: - protocol, host, port = resolveClusterIPOrTypeNodeServiceUriParams(service, customPort) - case corev1.ServiceTypeNodePort: - protocol, host, port = resolveClusterIPOrTypeNodeServiceUriParams(service, customPort) - case corev1.ServiceTypeLoadBalancer: - err = fmt.Errorf("Service type %s is not yet supported", service.Spec.Type) - default: - err = fmt.Errorf("Service type %s is not yet supported", service.Spec.Type) - } - if err != nil { - return "", err - } - if service.Spec.Type == corev1.ServiceTypeExternalName || outputFormat == KubernetesIPAddress { - return buildURI(protocol, host, port), nil - } else { - return buildKubernetesServiceDNSUri(protocol, service.Namespace, service.Name, port), nil - } -} - -// resolveClusterIPOrTypeNodeServiceUriParams returns the uri parameters for a service of type ClusterIP or TypeNode. -// The optional customPort can be used to determine which port should be used for the communication, when not set, -// the best suited port is returned. For this last, a secure port has precedence over a no-secure port. -func resolveClusterIPOrTypeNodeServiceUriParams(service *corev1.Service, customPort string) (protocol string, host string, port int) { - servicePort := findBestSuitedServicePort(service, customPort) - if isSecureServicePort(servicePort) { - protocol = httpsProtocol - } else { - protocol = httpProtocol - } - host = service.Spec.ClusterIP - port = int(servicePort.Port) - return protocol, host, port -} - -func resolvePodUri(pod *corev1.Pod, customContainer string, customPort string, outputFormat string) (string, error) { - if podIp := pod.Status.PodIP; len(podIp) == 0 { - return "", fmt.Errorf("pod: %s in namespace: %s, has no allocated address", pod.Name, pod.Namespace) - } else { - var container *corev1.Container - if len(customContainer) > 0 { - container, _ = kubernetes.GetContainerByName(customContainer, &pod.Spec) - } - if container == nil { - container = &pod.Spec.Containers[0] - } - if containerPort := findBestSuitedContainerPort(container, customPort); containerPort == nil { - return "", fmt.Errorf("no container port was found for pod: %s in namespace: %s", pod.Name, pod.Namespace) - } else { - protocol := httpProtocol - if isSecure := isSecureContainerPort(containerPort); isSecure { - protocol = httpsProtocol - } - if outputFormat == KubernetesDNSAddress { - return buildKubernetesPodDNSUri(protocol, pod.Namespace, podIp, int(containerPort.ContainerPort)), nil - } else { - return buildURI(protocol, podIp, int(containerPort.ContainerPort)), nil - } - } - } -} - -func buildURI(scheme string, host string, port int) string { - return fmt.Sprintf("%s://%s:%v", scheme, host, port) -} - -func buildKubernetesServiceDNSUri(scheme string, namespace string, name string, port int) string { - return fmt.Sprintf("%s://%s.%s.svc:%v", scheme, name, namespace, port) -} - -func buildKubernetesPodDNSUri(scheme string, namespace string, podIP string, port int) string { - hyphenedIp := strings.Replace(podIP, ".", "-", -1) - return fmt.Sprintf("%s://%s.%s.pod:%v", scheme, hyphenedIp, namespace, port) -} diff --git a/internal/controller/discovery/uri_utils_test.go b/internal/controller/discovery/uri_utils_test.go deleted file mode 100644 index 3d296114..00000000 --- a/internal/controller/discovery/uri_utils_test.go +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func Test_resolveServiceUriClusterIPServiceDNSMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - doTestResolveServiceUri(t, service, corev1.ServiceTypeClusterIP, KubernetesDNSAddress, "http://service1Name.namespace1.svc:80") -} - -func Test_resolveServiceUriClusterIPServiceIPAddressMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.ClusterIP = "10.1.15.16" - doTestResolveServiceUri(t, service, corev1.ServiceTypeClusterIP, KubernetesIPAddress, "http://10.1.15.16:80") -} - -func Test_resolveServiceUriNodeTypeServiceDNSMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - doTestResolveServiceUri(t, service, corev1.ServiceTypeNodePort, KubernetesDNSAddress, "http://service1Name.namespace1.svc:80") -} - -func Test_resolveServiceUriNodeTypeServiceIPAddressMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.ClusterIP = "10.1.15.16" - doTestResolveServiceUri(t, service, corev1.ServiceTypeNodePort, KubernetesIPAddress, "http://10.1.15.16:80") -} - -func Test_resolveServiceUriExternalNameServiceDNSMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.ExternalName = "external.service.com" - doTestResolveServiceUri(t, service, corev1.ServiceTypeExternalName, KubernetesIPAddress, "http://external.service.com:80") -} - -func Test_resolveServiceUriExternalNameServiceIPAddressMode(t *testing.T) { - service := mockServiceWithPorts(namespace1, service1Name, mockServicePort(httpProtocol, tcp, defaultHttpPort)) - service.Spec.ExternalName = "external.service.com" - doTestResolveServiceUri(t, service, corev1.ServiceTypeExternalName, KubernetesIPAddress, "http://external.service.com:80") -} - -func doTestResolveServiceUri(t *testing.T, service *corev1.Service, serviceType corev1.ServiceType, outputMode string, expectedUri string) { - service.Spec.Type = serviceType - result, err := resolveServiceUri(service, "", outputMode) - assert.NoError(t, err) - assert.Equal(t, expectedUri, result) -} - -func Test_resolvePodUriDNSMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpProtocol, tcp, defaultHttpPort)), - *mockContainerWithPorts(container2Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort))) - pod.Status.PodIP = "10.1.15.16" - doTestResolvePodUri(t, pod, "", "", KubernetesDNSAddress, "http://10-1-15-16.namespace1.pod:80") -} - -func Test_resolvePodUriIPAddressMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpProtocol, tcp, defaultHttpPort)), - *mockContainerWithPorts(container2Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort))) - pod.Status.PodIP = "10.1.15.17" - doTestResolvePodUri(t, pod, "", "", KubernetesIPAddress, "http://10.1.15.17:80") -} - -func Test_resolvePodUriByCustomContainerDNSMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)), - *mockContainerWithPorts("custom-container", mockContainerPort(httpProtocol, tcp, defaultHttpPort))) - pod.Status.PodIP = "10.1.15.16" - doTestResolvePodUri(t, pod, "custom-container", "", KubernetesDNSAddress, "http://10-1-15-16.namespace1.pod:80") -} - -func Test_resolvePodUriByCustomContainerIPAddressMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)), - *mockContainerWithPorts("custom-container", mockContainerPort(httpProtocol, tcp, defaultHttpPort))) - pod.Status.PodIP = "10.1.15.17" - doTestResolvePodUri(t, pod, "custom-container", "", KubernetesIPAddress, "http://10.1.15.17:80") -} - -func Test_resolvePodUriByCustomContainerAndCustomPortDNSMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)), - *mockContainerWithPorts("custom-container", - mockContainerPort("not-wanted", tcp, 8008), - mockContainerPort("custom-port", tcp, 8181))) - pod.Status.PodIP = "10.1.15.16" - doTestResolvePodUri(t, pod, "custom-container", "custom-port", KubernetesDNSAddress, "http://10-1-15-16.namespace1.pod:8181") -} - -func Test_resolvePodUriByCustomContainerAndCustomPortIPAddressMode(t *testing.T) { - pod := mockPodWithContainers(namespace1, pod1Name, - *mockContainerWithPorts(container1Name, mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)), - *mockContainerWithPorts("custom-container", - mockContainerPort("not-wanted", tcp, 8008), - mockContainerPort("custom-port", tcp, 8181))) - pod.Status.PodIP = "10.1.15.17" - doTestResolvePodUri(t, pod, "custom-container", "custom-port", KubernetesIPAddress, "http://10.1.15.17:8181") -} - -func doTestResolvePodUri(t *testing.T, pod *corev1.Pod, customContainer string, customPort, outputMode string, expectedUri string) { - result, err := resolvePodUri(pod, customContainer, customPort, outputMode) - assert.NoError(t, err) - assert.Equal(t, expectedUri, result) -} - -func Test_buildURI(t *testing.T) { - assert.Equal(t, "http://10.1.15.16:8383", buildURI("http", "10.1.15.16", 8383)) -} - -func Test_buildKubernetesServiceDNSUri(t *testing.T) { - assert.Equal(t, "http://service1Name.namespace1.svc:8383", buildKubernetesServiceDNSUri("http", namespace1, service1Name, 8383)) -} - -func Test_buildKubernetesPodDNSUri(t *testing.T) { - assert.Equal(t, "http://pod1Name.namespace1.pod:8484", buildKubernetesPodDNSUri("http", namespace1, pod1Name, 8484)) -} diff --git a/internal/controller/eventing/workflowdef_events.go b/internal/controller/eventing/workflowdef_events.go deleted file mode 100644 index 68fb549c..00000000 --- a/internal/controller/eventing/workflowdef_events.go +++ /dev/null @@ -1,73 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 eventing - -import ( - "context" - "fmt" - - duckv1 "knative.dev/pkg/apis/duck/v1" - - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" -) - -// GetWorkflowDefinitionEventsTargetURL returns the target url that must be used to send the workflow definition events. -func GetWorkflowDefinitionEventsTargetURL(cli client.Client, workflow *operatorapi.SonataFlow) (string, error) { - var err error - var sfp *operatorapi.SonataFlowPlatform - var sink *duckv1.Destination - var uri string - - if sfp, err = platform.GetActivePlatform(context.Background(), cli, workflow.Namespace, false); err != nil { - return "", fmt.Errorf("failed to get active platform for workflow: %s, namespace: %s : %v", workflow.Name, workflow.Namespace, err) - } - if sfp == nil { - klog.V(log.D).Infof("No active platform was found to calculate the workflow definition events target url for workflow: %s, namespace: %s.", workflow.Name, workflow.Namespace) - return "", err - } - diHandler := services.NewDataIndexHandler(sfp) - if !diHandler.IsServiceEnabled() { - klog.V(log.D).Infof("DataIndex is not enabled for current workflow: %s, namespace: %s, neither in current platform: %s, or by a cluster platform reference.", workflow.Name, workflow.Namespace, sfp.Name) - return "", nil - } - - // First check if the workflow is connected with the knative eventing system. - if sink, err = knative.GetWorkflowSink(workflow, sfp); err != nil { - return "", fmt.Errorf("failed to look for a potential sink configuration for workflow: %s, namespace: %s : %v", workflow.Name, workflow.Namespace, err) - } - if sink != nil { - // Workflow is connected via with knative eventing by using an operator managed SinkBinding. - if sinkURI, err := knative.GetSinkURI(*sink); err != nil { - return "", err - } else { - uri = sinkURI.String() - } - } else { - // Workflow is connected via direct http invocation with the DI. - uri = diHandler.GetServiceBaseUrl() + constants.KogitoProcessDefinitionsEventsPath - } - return uri, nil -} diff --git a/internal/controller/knative/knative.go b/internal/controller/knative/knative.go deleted file mode 100644 index 915df823..00000000 --- a/internal/controller/knative/knative.go +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 knative - -import ( - "context" - "fmt" - "sort" - "strings" - - "k8s.io/apimachinery/pkg/labels" - "k8s.io/klog/v2" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - "github.com/kubesmarts/logic-operator/log" - - "knative.dev/pkg/resolver" - - "knative.dev/pkg/tracker" - - "knative.dev/pkg/injection/clients/dynamicclient" - - "knative.dev/pkg/client/injection/ducks/duck/v1/addressable" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "knative.dev/eventing/pkg/apis/eventing" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - clienteventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" - clientservingv1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/utils" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -var servingClient clientservingv1.ServingV1Interface -var eventingClient clienteventingv1.EventingV1Interface - -type Availability struct { - Eventing bool - Serving bool -} - -const ( - kSink = "K_SINK" - knativeBundleVolume = "kne-bundle-volume" - kCeOverRides = "K_CE_OVERRIDES" - knativeServingGroup = "serving.knative.dev" - knativeEventingGroup = "eventing.knative.dev" - knativeEventingAPIVersion = "eventing.knative.dev/v1" - knativeBrokerKind = "Broker" - knativeSinkProvided = "SinkProvided" - KafkaKnativeEventingDeliveryOrder = "kafka.eventing.knative.dev/delivery.order" - KafkaKnativeEventingDeliveryOrderOrdered = "ordered" - workflowContainer = "workflow" -) - -// noOpTracker no operations tracker for querying operations based on resolver.URIResolver, that don't require any -// resource tracking but only resolving the URL. -// Note: knative team was asked, and it's valid to use a dummy tracker at the same time we benefit from the uri resolution. -// see: resolver.URIResolver -type noOpTracker struct { -} - -func (n noOpTracker) Track(ref corev1.ObjectReference, obj interface{}) error { - return nil -} - -func (n noOpTracker) TrackReference(ref tracker.Reference, obj interface{}) error { - return nil -} - -func (n noOpTracker) OnChanged(obj interface{}) { -} - -func (n noOpTracker) GetObservers(obj interface{}) []types.NamespacedName { - return nil -} - -func (n noOpTracker) OnDeletedObserver(obj interface{}) { -} - -func GetKnativeServingClient(cfg *rest.Config) (clientservingv1.ServingV1Interface, error) { - if servingClient == nil { - if knServingClient, err := NewKnativeServingClient(cfg); err != nil { - return nil, err - } else { - servingClient = knServingClient - } - } - return servingClient, nil -} - -func GetKnativeEventingClient(cfg *rest.Config) (clienteventingv1.EventingV1Interface, error) { - if eventingClient == nil { - if knEventingClient, err := NewKnativeEventingClient(cfg); err != nil { - return nil, err - } else { - eventingClient = knEventingClient - } - } - return eventingClient, nil -} - -func NewKnativeServingClient(cfg *rest.Config) (*clientservingv1.ServingV1Client, error) { - return clientservingv1.NewForConfig(cfg) -} - -func NewKnativeEventingClient(cfg *rest.Config) (*clienteventingv1.EventingV1Client, error) { - return clienteventingv1.NewForConfig(cfg) -} - -func GetKnativeAvailability(cfg *rest.Config) (*Availability, error) { - if cli, err := utils.GetDiscoveryClient(cfg); err != nil { - return nil, err - } else { - apiList, err := cli.ServerGroups() - if err != nil { - return nil, err - } - result := new(Availability) - for _, group := range apiList.Groups { - if group.Name == knativeServingGroup { - result.Serving = true - } - if group.Name == knativeEventingGroup { - result.Eventing = true - } - } - return result, nil - } -} - -// GetRemotePlatform returns the remote platform referred by a SonataFlowClusterPlatform if any. -func GetRemotePlatform(pl *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, error) { - if pl.Status.ClusterPlatformRef != nil { - // Find the platform referred by the cluster platform - platform := &operatorapi.SonataFlowPlatform{} - if err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Namespace: pl.Status.ClusterPlatformRef.PlatformRef.Namespace, Name: pl.Status.ClusterPlatformRef.PlatformRef.Name}, platform); err != nil { - return nil, fmt.Errorf("error reading the platform referred by the cluster platform") - } - return platform, nil - } - return nil, nil -} - -func getDestinationWithNamespace(dest *duckv1.Destination, namespace string) *duckv1.Destination { - if dest != nil && dest.Ref != nil && len(dest.Ref.Namespace) == 0 { - dest.Ref.Namespace = namespace - } - return dest -} - -func ValidateBroker(name, namespace string) (*eventingv1.Broker, error) { - broker := &eventingv1.Broker{} - if err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, broker); err != nil { - if errors.IsNotFound(err) { - return nil, fmt.Errorf("broker %s in namespace %s does not exist", name, namespace) - } - return nil, err - } - cond := broker.Status.GetCondition(apis.ConditionReady) - if cond != nil && cond.Status == corev1.ConditionTrue { - return broker, nil - } - return nil, fmt.Errorf("broker %s in namespace %s is not ready", name, namespace) -} - -// GetBrokerClass returns the broker class for a Knative Eventing Broker. -func GetBrokerClass(broker *eventingv1.Broker) string { - if broker.Annotations == nil { - return "" - } - return broker.Annotations[eventing.BrokerClassKey] -} - -// IsKafkaBroker returns true if the class for a Knative Eventing Broker corresponds to a Kafka broker. -func IsKafkaBroker(brokerClass string) bool { - // currently available kafka broker classes are "Kafka", and "KafkaNamespaced", for safety ask for the substring "Kafka". - return strings.Contains(brokerClass, "Kafka") -} - -func GetWorkflowSink(workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform) (*duckv1.Destination, error) { - if workflow == nil { - return nil, nil - } - if workflow.Spec.Sink != nil { - return getDestinationWithNamespace(workflow.Spec.Sink, workflow.Namespace), nil - } - if pl == nil { - return nil, nil - } - if pl.Spec.Eventing != nil && pl.Spec.Eventing.Broker != nil { - // no sink defined in the workflow, use the platform broker - return getDestinationWithNamespace(pl.Spec.Eventing.Broker, pl.Namespace), nil - } - // Find the remote platform referred by the cluster platform - platform, err := GetRemotePlatform(pl) - if err != nil { - return nil, err - } - if platform != nil && platform.Spec.Eventing != nil && platform.Spec.Eventing.Broker != nil { - return getDestinationWithNamespace(platform.Spec.Eventing.Broker, platform.Namespace), nil - } - return nil, nil -} - -func IsKnativeBroker(kRef *duckv1.KReference) bool { - return kRef.APIVersion == knativeEventingAPIVersion && kRef.Kind == knativeBrokerKind -} - -func SaveKnativeData(dest *corev1.PodSpec, source *corev1.PodSpec) { - for _, volume := range source.Volumes { - if volume.Name == knativeBundleVolume { - kubeutil.AddOrReplaceVolume(dest, volume) - break - } - } - visitContainers(source, func(container *corev1.Container) { - visitContainers(dest, func(destContainer *corev1.Container) { - for _, mount := range container.VolumeMounts { - if mount.Name == knativeBundleVolume { - kubeutil.AddOrReplaceVolumeMount(destContainer, mount) - break - } - } - for _, env := range container.Env { - if env.Name == kSink || env.Name == kCeOverRides { - kubeutil.AddOrReplaceEnvVar(destContainer, env) - } - } - }) - }) -} - -func moveKnativeVolumeToEnd(vols []corev1.Volume) { - for i := 0; i < len(vols)-1; i++ { - if vols[i].Name == knativeBundleVolume { - vols[i], vols[i+1] = vols[i+1], vols[i] - } - } -} - -func moveKnativeVolumeMountToEnd(mounts []corev1.VolumeMount) { - for i := 0; i < len(mounts)-1; i++ { - if mounts[i].Name == knativeBundleVolume { - mounts[i], mounts[i+1] = mounts[i+1], mounts[i] - } - } -} - -// Knative Sinkbinding injects K_SINK env, a volume and volume mount. The volume and volume mount -// must be in the end of the array to avoid repeadly restarting of the workflow pod -func RestoreKnativeVolumeAndVolumeMount(podSpec *corev1.PodSpec) { - moveKnativeVolumeToEnd(podSpec.Volumes) - visitContainers(podSpec, func(container *corev1.Container) { - moveKnativeVolumeMountToEnd(container.VolumeMounts) - }) -} - -// containerVisitor is called with each container -type containerVisitor func(container *corev1.Container) - -// visitContainers invokes the visitor function for every container in the given pod template spec -func visitContainers(podSpec *corev1.PodSpec, visitor containerVisitor) { - for i := range podSpec.InitContainers { - visitor(&podSpec.InitContainers[i]) - } - for i := range podSpec.Containers { - visitor(&podSpec.Containers[i]) - } - for i := range podSpec.EphemeralContainers { - visitor((*corev1.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon)) - } -} - -// if a trigger is changed and it has namespace different from the platform is changed, reconcile the parent SonataFlowPlatform in the cluster. -func MapTriggerToPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - if trigger, ok := object.(*eventingv1.Trigger); ok { - nameFound := "" - namespaceFound := "" - for k, v := range trigger.GetLabels() { - if k == workflowproj.LabelApp { - nameFound = v - } else if k == workflowproj.LabelAppNamespace { - namespaceFound = v - } - } - if len(nameFound) > 0 && len(namespaceFound) > 0 && namespaceFound != trigger.Namespace { - return []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nameFound, Namespace: namespaceFound}}} - } - } - return nil -} - -// Does the sinkbinding completed K_SINK injection? -func CheckKSinkInjected(name, namespace string) (bool, error) { - sb := &sourcesv1.SinkBinding{} - if err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf("%s-sb", name), Namespace: namespace}, sb); err != nil { - if errors.IsNotFound(err) { - return false, nil // deployment hasn't been created yet - } - return false, err - } - cond := sb.Status.GetCondition(apis.ConditionType(knativeSinkProvided)) - if cond != nil && cond.Status == corev1.ConditionTrue { - return true, nil - } - return false, nil // K_SINK has not been injected yet -} - -// GetSinkBindingSinkURI returns the address of the sink referred by a SinkBinding. -func GetSinkBindingSinkURI(name, namespace string) (*apis.URL, error) { - sb := &sourcesv1.SinkBinding{} - if err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, sb); err != nil { - return nil, err - } - cond := sb.Status.GetCondition(apis.ConditionType(apis.ConditionReady)) - if cond == nil || cond.Status != corev1.ConditionTrue { - return nil, fmt.Errorf("SinkBinding name: %s, namespace: %s is not ready", name, namespace) - } - return sb.Status.SinkURI, nil -} - -// GetSinkURI returns the address of the sink referred by a Destination. -func GetSinkURI(destination duckv1.Destination) (*apis.URL, error) { - ctx := context.WithValue(context.TODO(), dynamicclient.Key{}, utils.GetDynamicClient()) - ctx = addressable.WithDuck(ctx) - uriResolver := resolver.NewURIResolverFromTracker(ctx, &noOpTracker{}) - if url, err := uriResolver.URIFromDestinationV1(ctx, destination, nil); err != nil { - return nil, err - } else { - return url, nil - } -} - -// CleanupOutdatedRevisions Given a deployed workflow, analyses if the configured deployment model is knative. -// If that is the case, and the corresponding SinkBinding was created and properly injected, all the previous knative -// service revisions that weren't properly initialized (i.e. doesn't have the K_SINK injected) will be cleaned-up. -// Note that revisions in that situation are not valid, since workflows without the K_SINK injected will never pass -// the health checks, etc. -func CleanupOutdatedRevisions(ctx context.Context, cfg *rest.Config, workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) error { - if !workflow.IsKnativeDeployment() { - return nil - } - avail, err := GetKnativeAvailability(cfg) - if err != nil { - return err - } - if !avail.Serving || !avail.Eventing { - return nil - } - sink, err := GetWorkflowSink(workflow, platform) - if err != nil { - return fmt.Errorf("failed to get workflow sink for workflow : %s, namespace: %s : %v", workflow.Name, workflow.Namespace, err) - } - if sink == nil { - // no sink?, then no SinkBinding required/created for this workflow, and thus no dangling revisions to clean. - return nil - } - injected, err := CheckKSinkInjected(workflow.Name, workflow.Namespace) - if err != nil { - return err - } - if !injected { - return fmt.Errorf("waiting for Sinkbinding K_SINK injection to complete") - } - opts := &client.ListOptions{ - LabelSelector: labels.SelectorFromSet( - map[string]string{ - workflowproj.LabelWorkflow: workflow.Name, - workflowproj.LabelWorkflowNamespace: workflow.Namespace, - }, - ), - Namespace: workflow.Namespace, - } - revisionList := &servingv1.RevisionList{} - if err := utils.GetClient().List(ctx, revisionList, opts); err != nil { - return err - } - // Sort the revisions based on creation timestamp - sortRevisions(revisionList.Items) - // Clean up previous revisions that do not have K_SINK injected - for i := 0; i < len(revisionList.Items)-1; i++ { - revision := &revisionList.Items[i] - if !containsKSink(revision) { - klog.V(log.I).InfoS("Revision %s does not have K_SINK injected and can be cleaned up.", revision.Name) - if err := utils.GetClient().Delete(ctx, revision, &client.DeleteOptions{}); err != nil { - return err - } - } - } - return nil -} - -func containsKSink(revision *servingv1.Revision) bool { - for _, container := range revision.Spec.PodSpec.Containers { - if container.Name == workflowContainer { - for _, env := range container.Env { - if env.Name == kSink { - return true - } - } - break - } - } - return false -} - -type CreationTimestamp []servingv1.Revision - -func (a CreationTimestamp) Len() int { return len(a) } -func (a CreationTimestamp) Less(i, j int) bool { - return a[i].CreationTimestamp.Before(&a[j].CreationTimestamp) -} -func (a CreationTimestamp) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func sortRevisions(revisions []servingv1.Revision) { - sort.Sort(CreationTimestamp(revisions)) -} diff --git a/internal/controller/logicflowdefinition_controller.go b/internal/controller/logicflowdefinition_controller.go new file mode 100644 index 00000000..9811134a --- /dev/null +++ b/internal/controller/logicflowdefinition_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +// LogicFlowDefinitionReconciler reconciles a LogicFlowDefinition object +type LogicFlowDefinitionReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowdefinitions,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowdefinitions/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowdefinitions/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the LogicFlowDefinition object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile +func (r *LogicFlowDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = logf.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *LogicFlowDefinitionReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&logicv1.LogicFlowDefinition{}). + Named("logicflowdefinition"). + Complete(r) +} diff --git a/internal/controller/logicflowdefinition_controller_test.go b/internal/controller/logicflowdefinition_controller_test.go new file mode 100644 index 00000000..8c9d0abd --- /dev/null +++ b/internal/controller/logicflowdefinition_controller_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +var _ = Describe("LogicFlowDefinition Controller", func() { + Context("When reconciling a resource", func() { + const resourceName = "test-resource" + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", // TODO(user):Modify as needed + } + logicflowdefinition := &logicv1.LogicFlowDefinition{} + + BeforeEach(func() { + By("creating the custom resource for the Kind LogicFlowDefinition") + err := k8sClient.Get(ctx, typeNamespacedName, logicflowdefinition) + if err != nil && errors.IsNotFound(err) { + resource := &logicv1.LogicFlowDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + // TODO(user): Specify other spec details if needed. + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterEach(func() { + // TODO(user): Cleanup logic after each test, like removing the resource instance. + resource := &logicv1.LogicFlowDefinition{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance LogicFlowDefinition") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &LogicFlowDefinitionReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. + // Example: If you expect a certain status condition after reconciliation, verify it here. + }) + }) +}) diff --git a/internal/controller/logicflowruntime_controller.go b/internal/controller/logicflowruntime_controller.go new file mode 100644 index 00000000..33e34e28 --- /dev/null +++ b/internal/controller/logicflowruntime_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +// LogicFlowRuntimeReconciler reconciles a LogicFlowRuntime object +type LogicFlowRuntimeReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowruntimes,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowruntimes/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowruntimes/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the LogicFlowRuntime object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile +func (r *LogicFlowRuntimeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = logf.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *LogicFlowRuntimeReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&logicv1.LogicFlowRuntime{}). + Named("logicflowruntime"). + Complete(r) +} diff --git a/internal/controller/logicflowruntime_controller_test.go b/internal/controller/logicflowruntime_controller_test.go new file mode 100644 index 00000000..d2e0f92c --- /dev/null +++ b/internal/controller/logicflowruntime_controller_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +var _ = Describe("LogicFlowRuntime Controller", func() { + Context("When reconciling a resource", func() { + const resourceName = "test-resource" + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", // TODO(user):Modify as needed + } + logicflowruntime := &logicv1.LogicFlowRuntime{} + + BeforeEach(func() { + By("creating the custom resource for the Kind LogicFlowRuntime") + err := k8sClient.Get(ctx, typeNamespacedName, logicflowruntime) + if err != nil && errors.IsNotFound(err) { + resource := &logicv1.LogicFlowRuntime{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + // TODO(user): Specify other spec details if needed. + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterEach(func() { + // TODO(user): Cleanup logic after each test, like removing the resource instance. + resource := &logicv1.LogicFlowRuntime{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance LogicFlowRuntime") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &LogicFlowRuntimeReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. + // Example: If you expect a certain status condition after reconciliation, verify it here. + }) + }) +}) diff --git a/internal/controller/logicflowservice_controller.go b/internal/controller/logicflowservice_controller.go new file mode 100644 index 00000000..d63f0191 --- /dev/null +++ b/internal/controller/logicflowservice_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +// LogicFlowServiceReconciler reconciles a LogicFlowService object +type LogicFlowServiceReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowservices,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowservices/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicflowservices/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the LogicFlowService object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile +func (r *LogicFlowServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = logf.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *LogicFlowServiceReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&logicv1.LogicFlowService{}). + Named("logicflowservice"). + Complete(r) +} diff --git a/internal/controller/logicflowservice_controller_test.go b/internal/controller/logicflowservice_controller_test.go new file mode 100644 index 00000000..44fce2a6 --- /dev/null +++ b/internal/controller/logicflowservice_controller_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +var _ = Describe("LogicFlowService Controller", func() { + Context("When reconciling a resource", func() { + const resourceName = "test-resource" + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", // TODO(user):Modify as needed + } + logicflowservice := &logicv1.LogicFlowService{} + + BeforeEach(func() { + By("creating the custom resource for the Kind LogicFlowService") + err := k8sClient.Get(ctx, typeNamespacedName, logicflowservice) + if err != nil && errors.IsNotFound(err) { + resource := &logicv1.LogicFlowService{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + // TODO(user): Specify other spec details if needed. + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterEach(func() { + // TODO(user): Cleanup logic after each test, like removing the resource instance. + resource := &logicv1.LogicFlowService{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance LogicFlowService") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &LogicFlowServiceReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. + // Example: If you expect a certain status condition after reconciliation, verify it here. + }) + }) +}) diff --git a/internal/controller/logicplatform_controller.go b/internal/controller/logicplatform_controller.go new file mode 100644 index 00000000..c7442282 --- /dev/null +++ b/internal/controller/logicplatform_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +// LogicPlatformReconciler reconciles a LogicPlatform object +type LogicPlatformReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicplatforms,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicplatforms/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logic.kubesmarts.org,resources=logicplatforms/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the LogicPlatform object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile +func (r *LogicPlatformReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = logf.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *LogicPlatformReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&logicv1.LogicPlatform{}). + Named("logicplatform"). + Complete(r) +} diff --git a/internal/controller/logicplatform_controller_test.go b/internal/controller/logicplatform_controller_test.go new file mode 100644 index 00000000..bf0f4ffe --- /dev/null +++ b/internal/controller/logicplatform_controller_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + logicv1 "github.com/kubesmarts/logic-operator/api/v1" +) + +var _ = Describe("LogicPlatform Controller", func() { + Context("When reconciling a resource", func() { + const resourceName = "test-resource" + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", // TODO(user):Modify as needed + } + logicplatform := &logicv1.LogicPlatform{} + + BeforeEach(func() { + By("creating the custom resource for the Kind LogicPlatform") + err := k8sClient.Get(ctx, typeNamespacedName, logicplatform) + if err != nil && errors.IsNotFound(err) { + resource := &logicv1.LogicPlatform{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + // TODO(user): Specify other spec details if needed. + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterEach(func() { + // TODO(user): Cleanup logic after each test, like removing the resource instance. + resource := &logicv1.LogicPlatform{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance LogicPlatform") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &LogicPlatformReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. + // Example: If you expect a certain status condition after reconciliation, verify it here. + }) + }) +}) diff --git a/internal/controller/monitoring/monitoring.go b/internal/controller/monitoring/monitoring.go deleted file mode 100644 index f20ded48..00000000 --- a/internal/controller/monitoring/monitoring.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 monitoring - -import ( - "k8s.io/client-go/rest" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/utils" -) - -const ( - prometheusGroup = "monitoring.coreos.com" -) - -func GetPrometheusAvailability(cfg *rest.Config) (bool, error) { - cli, err := utils.GetDiscoveryClient(cfg) - if err != nil { - return false, err - } - apiList, err := cli.ServerGroups() - if err != nil { - return false, err - } - for _, group := range apiList.Groups { - if group.Name == prometheusGroup { - return true, nil - } - - } - return false, nil -} - -func IsMonitoringEnabled(pl *operatorapi.SonataFlowPlatform) bool { - return pl != nil && pl.Spec.Monitoring != nil && pl.Spec.Monitoring.Enabled -} diff --git a/internal/controller/openshift/openshift.go b/internal/controller/openshift/openshift.go deleted file mode 100644 index 57abc481..00000000 --- a/internal/controller/openshift/openshift.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 openshift - -import ( - appsv1 "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1" - buildv1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1" - routev1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" - "k8s.io/client-go/rest" -) - -var routeClient routev1.RouteV1Interface -var appsClient appsv1.AppsV1Interface - -func GetRouteClient(cfg *rest.Config) (routev1.RouteV1Interface, error) { - if routeClient == nil { - if osRouteClient, err := NewOpenShiftRouteClient(cfg); err != nil { - return nil, err - } else { - routeClient = osRouteClient - } - } - return routeClient, nil -} - -func GetAppsClient(cfg *rest.Config) (appsv1.AppsV1Interface, error) { - if appsClient == nil { - if osAppsClient, err := NewOpenShiftAppsClientClient(cfg); err != nil { - return nil, err - } else { - appsClient = osAppsClient - } - } - return appsClient, nil -} - -func NewOpenShiftRouteClient(cfg *rest.Config) (*routev1.RouteV1Client, error) { - return routev1.NewForConfig(cfg) -} - -func NewOpenShiftAppsClientClient(cfg *rest.Config) (*appsv1.AppsV1Client, error) { - return appsv1.NewForConfig(cfg) -} - -func NewOpenShiftBuildClient(cfg *rest.Config) (*buildv1.BuildV1Client, error) { - return buildv1.NewForConfig(cfg) -} diff --git a/internal/controller/platform/action.go b/internal/controller/platform/action.go deleted file mode 100644 index 2ef1bd59..00000000 --- a/internal/controller/platform/action.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - - v08 "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -// Action --. -type Action interface { - client.Injectable - - // a user friendly name for the action - Name() string - - // returns true if the action can handle the platform - CanHandle(platform *v08.SonataFlowPlatform) bool - - // executes the handling function - Handle(ctx context.Context, platform *v08.SonataFlowPlatform) (*v08.SonataFlowPlatform, *corev1.Event, error) -} - -type baseAction struct { - client client.Client -} - -func (action *baseAction) InjectClient(client client.Client) { - action.client = client -} diff --git a/internal/controller/platform/create.go b/internal/controller/platform/create.go deleted file mode 100644 index 21d0f4c7..00000000 --- a/internal/controller/platform/create.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/api" - v08 "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -// NewCreateAction returns an action that creates resources needed by the platform. -func NewCreateAction() Action { - return &createAction{} -} - -type createAction struct { - baseAction -} - -func (action *createAction) Name() string { - return "create" -} - -func (action *createAction) CanHandle(platform *v08.SonataFlowPlatform) bool { - return platform.Status.IsCreating() -} - -func (action *createAction) Handle(ctx context.Context, platform *v08.SonataFlowPlatform) (*v08.SonataFlowPlatform, *corev1.Event, error) { - //TODO: Perform the actions needed for the Platform creation - platform.Status.Manager().MarkTrue(api.SucceedConditionType) - - return platform, nil, nil -} diff --git a/internal/controller/platform/db_migrator_job.go b/internal/controller/platform/db_migrator_job.go deleted file mode 100644 index 78ee1a7d..00000000 --- a/internal/controller/platform/db_migrator_job.go +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "errors" - "fmt" - "hash/fnv" - "strconv" - - "github.com/kubesmarts/logic-operator/api/version" - "github.com/kubesmarts/logic-operator/utils/kubernetes" - - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/klog/v2" - "k8s.io/utils/pointer" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - "github.com/kubesmarts/logic-operator/log" -) - -type QuarkusDataSource struct { - JdbcUrl string - SecretRefName string - SecretUserKey string - SecretPasswordKey string - Schema string -} - -type DBMigratorJob struct { - Name string - Data DBMigratorJobData -} - -type DBMigratorJobData struct { - MigrateDBDataIndex bool - DataIndexDataSource *QuarkusDataSource - MigrateDBJobsService bool - JobsServiceDataSource *QuarkusDataSource -} - -type DBMigratorJobStatus struct { - Name string - BatchJobStatus *batchv1.JobStatus -} - -const ( - dbMigrationJobName = "sonataflow-db-migrator-job" - dbMigrationContainerName = "db-migration-container" - dbMigrationJobFailed = 1 - dbMigrationJobSucceeded = 1 - - migrateDBDataIndex = "MIGRATE_DB_DATAINDEX" - quarkusDataSourceDataIndexJdbcURL = "QUARKUS_DATASOURCE_DATAINDEX_JDBC_URL" - quarkusDataSourceDataIndexUserName = "QUARKUS_DATASOURCE_DATAINDEX_USERNAME" - quarkusDataSourceDataIndexPassword = "QUARKUS_DATASOURCE_DATAINDEX_PASSWORD" - quarkusFlywayDataIndexSchemas = "QUARKUS_FLYWAY_DATAINDEX_SCHEMAS" - - migrateDBJobsService = "MIGRATE_DB_JOBSSERVICE" - quarkusDataSourceJobsServiceJdbcURL = "QUARKUS_DATASOURCE_JOBSSERVICE_JDBC_URL" - quarkusDataSourceJobsServiceUserName = "QUARKUS_DATASOURCE_JOBSSERVICE_USERNAME" - quarkusDataSourceJobsServicePassword = "QUARKUS_DATASOURCE_JOBSSERVICE_PASSWORD" - quarkusFlywayJobsServiceSchemas = "QUARKUS_FLYWAY_JOBSSERVICE_SCHEMAS" - defaultPostgreSqlUserKey = "POSTGRESQL_USER" - defaultPostgreSqlPassworkdKey = "POSTGRESQL_PASSWORD" -) - -type DBMigrationJobCfg struct { - JobName string - ContainerName string - ToolImageName string -} - -func getJdbcUrl(env []corev1.EnvVar) string { - if env != nil { - for i := 0; i < len(env); i++ { - if env[i].Name == "QUARKUS_DATASOURCE_JDBC_URL" { - return env[i].Value - } - } - } - return "" -} - -func getDbMigratorJobName(version string) (string, error) { - h := fnv.New32a() - _, err := h.Write([]byte(version)) - if err != nil { - return "", fmt.Errorf("failed to calculate sonataflow-db-migrator job name for version: %s, %v", version, err) - } - return fmt.Sprintf("%s-%x", dbMigrationJobName, h.Sum32()), nil -} - -// getQuarkusDSFromServicePersistence Returns QuarkusDataSource from service level persistence config -func getQuarkusDSFromServicePersistence(platform *operatorapi.SonataFlowPlatform, persistenceOptionsSpec *operatorapi.PersistenceOptionsSpec, defaultSchemaName string) *QuarkusDataSource { - klog.InfoS("Using service level persistence for PostgreSQL", "defaultSchemaName", defaultSchemaName) - quarkusDataSource := &QuarkusDataSource{} - env := persistence.ConfigurePostgreSQLEnv(persistenceOptionsSpec.PostgreSQL, defaultSchemaName, platform.Namespace, false) - quarkusDataSource.JdbcUrl = getJdbcUrl(env) - quarkusDataSource.SecretRefName = persistenceOptionsSpec.PostgreSQL.SecretRef.Name - quarkusDataSource.SecretUserKey = defaultPostgreSqlUserKey - if len(persistenceOptionsSpec.PostgreSQL.SecretRef.UserKey) > 0 { - quarkusDataSource.SecretUserKey = persistenceOptionsSpec.PostgreSQL.SecretRef.UserKey - } - quarkusDataSource.SecretPasswordKey = defaultPostgreSqlPassworkdKey - if len(persistenceOptionsSpec.PostgreSQL.SecretRef.PasswordKey) > 0 { - quarkusDataSource.SecretPasswordKey = persistenceOptionsSpec.PostgreSQL.SecretRef.PasswordKey - } - quarkusDataSource.Schema = persistence.GetDBSchemaName(persistenceOptionsSpec.PostgreSQL, defaultSchemaName) - return quarkusDataSource -} - -// getQuarkusDSFromPlatformPersistence Returns QuarkusDataSource from platform level persistence config -func getQuarkusDSFromPlatformPersistence(platform *operatorapi.SonataFlowPlatform, defaultSchemaName string) *QuarkusDataSource { - klog.InfoS("Using platform level persistence for PostgreSQL", "defaultSchemaName", defaultSchemaName) - quarkusDataSource := &QuarkusDataSource{} - postgresql := persistence.MapToPersistencePostgreSQL(platform, defaultSchemaName) - - env := persistence.ConfigurePostgreSQLEnv(postgresql, defaultSchemaName, platform.Namespace, false) - quarkusDataSource.JdbcUrl = getJdbcUrl(env) - quarkusDataSource.SecretRefName = platform.Spec.Persistence.PostgreSQL.SecretRef.Name - quarkusDataSource.SecretUserKey = defaultPostgreSqlUserKey - if len(platform.Spec.Persistence.PostgreSQL.SecretRef.UserKey) > 0 { - quarkusDataSource.SecretUserKey = platform.Spec.Persistence.PostgreSQL.SecretRef.UserKey - } - quarkusDataSource.SecretPasswordKey = defaultPostgreSqlPassworkdKey - if len(platform.Spec.Persistence.PostgreSQL.SecretRef.PasswordKey) > 0 { - quarkusDataSource.SecretPasswordKey = platform.Spec.Persistence.PostgreSQL.SecretRef.PasswordKey - } - quarkusDataSource.Schema = persistence.GetDBSchemaName(postgresql, defaultSchemaName) - return quarkusDataSource -} - -// getQuarkusDataSourceFromPersistence PostgreSQL persistence can be defined at platform level (where both DI and JS will use the same DB defined at platform level) or db can defined at Service level. Service level config will take precedence over platform level config. -func getQuarkusDataSourceFromPersistence(platform *operatorapi.SonataFlowPlatform, persistenceOptionsSpec *operatorapi.PersistenceOptionsSpec, defaultSchemaName string) *QuarkusDataSource { - - if persistenceOptionsSpec != nil && persistenceOptionsSpec.PostgreSQL != nil { - return getQuarkusDSFromServicePersistence(platform, persistenceOptionsSpec, defaultSchemaName) - } else if platform != nil && platform.Spec.Persistence != nil && platform.Spec.Persistence.PostgreSQL != nil { - return getQuarkusDSFromPlatformPersistence(platform, defaultSchemaName) - } - - return nil -} - -func NewDBMigratorJobData(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, pshDI services.PlatformServiceHandler, pshJS services.PlatformServiceHandler) *DBMigratorJobData { - - diJobsBasedDBMigration := false - jsJobsBasedDBMigration := false - - if pshDI.IsPersistenceEnabledtInSpec() { - diJobsBasedDBMigration = services.IsJobsBasedDBMigration(platform.Spec.Services.DataIndex.Persistence) - } - if pshJS.IsPersistenceEnabledtInSpec() { - jsJobsBasedDBMigration = services.IsJobsBasedDBMigration(platform.Spec.Services.JobService.Persistence) - } - - if (pshDI.IsServiceSetInSpec() && diJobsBasedDBMigration) || (pshJS.IsServiceSetInSpec() && jsJobsBasedDBMigration) { - quarkusDataSourceDataIndex := &QuarkusDataSource{} - quarkusDataSourceJobService := &QuarkusDataSource{} - - if diJobsBasedDBMigration { - quarkusDataSourceDataIndex = getQuarkusDataSourceFromPersistence(platform, platform.Spec.Services.DataIndex.Persistence, pshDI.GetServiceName()) - } - - if jsJobsBasedDBMigration { - quarkusDataSourceJobService = getQuarkusDataSourceFromPersistence(platform, platform.Spec.Services.JobService.Persistence, pshJS.GetServiceName()) - } - - return &DBMigratorJobData{ - MigrateDBDataIndex: diJobsBasedDBMigration, - DataIndexDataSource: quarkusDataSourceDataIndex, - MigrateDBJobsService: jsJobsBasedDBMigration, - JobsServiceDataSource: quarkusDataSourceJobService, - } - } - return nil -} - -// IsJobsBasedDBMigration returns whether job based db migration approach is needed? -func IsJobsBasedDBMigration(platform *operatorapi.SonataFlowPlatform, pshDI services.PlatformServiceHandler, pshJS services.PlatformServiceHandler) bool { - diJobsBasedDBMigration := false - jsJobsBasedDBMigration := false - - if pshDI.IsPersistenceEnabledtInSpec() { - diJobsBasedDBMigration = services.IsJobsBasedDBMigration(platform.Spec.Services.DataIndex.Persistence) - } - if pshJS.IsPersistenceEnabledtInSpec() { - jsJobsBasedDBMigration = services.IsJobsBasedDBMigration(platform.Spec.Services.JobService.Persistence) - } - - return (pshDI.IsServiceSetInSpec() && diJobsBasedDBMigration) || (pshJS.IsServiceSetInSpec() && jsJobsBasedDBMigration) -} - -func createOrUpdateDBMigrationJob(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, pshDI services.PlatformServiceHandler, pshJS services.PlatformServiceHandler) (*DBMigratorJob, error) { - dbMigratorJobData := NewDBMigratorJobData(ctx, client, platform, pshDI, pshJS) - var dbMigratorJob *DBMigratorJob - - // Invoke DB Migration only if both or either DI/JS services are requested, in addition to DBMigrationStrategyJob - if dbMigratorJobData != nil { - jobName, err := getDbMigratorJobName(version.GetImageTagVersion()) - if err != nil { - return nil, err - } - dbMigratorJob = &DBMigratorJob{ - Name: jobName, - Data: *dbMigratorJobData, - } - currentJob, err := kubernetes.FindJob(ctx, client, platform.Namespace, jobName) - if err != nil { - return nil, fmt.Errorf("failed to detect if the job %s/%s already exists, %v", platform.Namespace, jobName, err) - } - if currentJob == nil { - // The job about to be created do not exist, we might be in the middle of a version N to version N+1 upgrade, or the regular creation. - // Delete DI and JS deployments if present for safety, we must avoid serving requests during the DB schema migration. (Unexpected results, data, etc., might happen) - // Both will be recreated in upcoming recon cycle after the job finishes. (we can keep the respective Services if already created to keep better response time) - if err = kubernetes.SafeDeleteDeployment(ctx, client, platform.Namespace, pshDI.GetServiceName()); err != nil { - return nil, fmt.Errorf("failed to delete DI deployment: %s/%s, %v", platform.Namespace, pshDI.GetServiceName(), err) - } - if err = kubernetes.SafeDeleteDeployment(ctx, client, platform.Namespace, pshJS.GetServiceName()); err != nil { - return nil, fmt.Errorf("failed to delete JS deployment: %s/%s, %v", platform.Namespace, pshJS.GetServiceName(), err) - } - } - job := createJobDBMigration(platform, dbMigratorJob) - klog.V(log.I).InfoS("Starting DB Migration Job: ", "namespace", platform.Namespace, "job", job.Name) - if err := controllerutil.SetControllerReference(platform, job, client.Scheme()); err != nil { - return nil, err - } - if op, err := controllerutil.CreateOrUpdate(ctx, client, job, func() error { - return nil - }); err != nil { - return dbMigratorJob, err - } else { - klog.V(log.I).InfoS("DB Migration Job successfully created on cluster", "operation", op, "namespace", platform.Namespace, "job", job.Name) - } - } - return dbMigratorJob, nil -} - -// HandleDBMigrationJob Creates db migration job and executes it on the cluster -func HandleDBMigrationJob(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psDI services.PlatformServiceHandler, psJS services.PlatformServiceHandler) (*operatorapi.SonataFlowPlatform, error) { - - dbMigratorJob, err := createOrUpdateDBMigrationJob(ctx, client, platform, psDI, psJS) - if err != nil { - return nil, err - } - if dbMigratorJob != nil { - klog.V(log.E).InfoS("Created DB migration job") - dbMigratorJobStatus, err := dbMigratorJob.ReconcileDBMigrationJob(ctx, client, platform) - if err != nil { - return nil, err - } - if hasFailed(dbMigratorJobStatus) { - return nil, errors.New("DB migration job " + dbMigratorJobStatus.Name + " failed in namespace: " + platform.Namespace) - } else if hasSucceeded(dbMigratorJobStatus) { - return platform, nil - } else { - // DB migration is still running - return nil, nil - } - } - - return platform, nil -} - -func newQuarkusDataSource(jdbcURL string, secretRefName string, secretUserKey string, secretPasswordKey string, schema string) *QuarkusDataSource { - return &QuarkusDataSource{ - JdbcUrl: jdbcURL, - SecretRefName: secretRefName, - SecretUserKey: secretUserKey, - SecretPasswordKey: secretPasswordKey, - Schema: schema, - } -} - -func createJobDBMigration(platform *operatorapi.SonataFlowPlatform, dbmj *DBMigratorJob) *batchv1.Job { - // In DB Migrator Tool, smallrye will throw error for empty string "" while initializing properties. - // So use an empty space as a default value. Please see more at: https://github.com/eclipse/microprofile-config/issues/671 - nonEmptyValue := " " - diQuarkusDataSource := newQuarkusDataSource(nonEmptyValue, nonEmptyValue, nonEmptyValue, nonEmptyValue, nonEmptyValue) - jsQuarkusDataSource := newQuarkusDataSource(nonEmptyValue, nonEmptyValue, nonEmptyValue, nonEmptyValue, nonEmptyValue) - - if dbmj.Data.MigrateDBDataIndex && dbmj.Data.DataIndexDataSource != nil { - diQuarkusDataSource.JdbcUrl = dbmj.Data.DataIndexDataSource.JdbcUrl - diQuarkusDataSource.SecretRefName = dbmj.Data.DataIndexDataSource.SecretRefName - diQuarkusDataSource.SecretUserKey = dbmj.Data.DataIndexDataSource.SecretUserKey - diQuarkusDataSource.SecretPasswordKey = dbmj.Data.DataIndexDataSource.SecretPasswordKey - diQuarkusDataSource.Schema = dbmj.Data.DataIndexDataSource.Schema - } - - if dbmj.Data.MigrateDBJobsService && dbmj.Data.JobsServiceDataSource != nil { - jsQuarkusDataSource.JdbcUrl = dbmj.Data.JobsServiceDataSource.JdbcUrl - jsQuarkusDataSource.SecretRefName = dbmj.Data.JobsServiceDataSource.SecretRefName - jsQuarkusDataSource.SecretUserKey = dbmj.Data.JobsServiceDataSource.SecretUserKey - jsQuarkusDataSource.SecretPasswordKey = dbmj.Data.JobsServiceDataSource.SecretPasswordKey - jsQuarkusDataSource.Schema = dbmj.Data.JobsServiceDataSource.Schema - } - - diDBSecretRef := corev1.LocalObjectReference{ - Name: diQuarkusDataSource.SecretRefName, - } - - jsDBSecretRef := corev1.LocalObjectReference{ - Name: jsQuarkusDataSource.SecretRefName, - } - - dbMigrationJobCfg := newDBMigrationJobCfg(dbmj.Name) - - lbl, _ := getServicesLabelsMap(platform.Name, platform.Namespace, fmt.Sprintf("%s-%s", "sonataflow-db-job", dbMigrationJobCfg.JobName), dbMigrationJobCfg.JobName, fmt.Sprintf("%s-%s", platform.Name, dbMigrationJobCfg.JobName), platform.Name, "sonataflow-operator") - - envVars := make([]corev1.EnvVar, 0) - envVars = append(envVars, corev1.EnvVar{ - Name: migrateDBDataIndex, - Value: strconv.FormatBool(dbmj.Data.MigrateDBDataIndex), - }) - if dbmj.Data.MigrateDBDataIndex { - envVars = append(envVars, - corev1.EnvVar{ - Name: quarkusDataSourceDataIndexJdbcURL, - Value: diQuarkusDataSource.JdbcUrl, - }, - corev1.EnvVar{ - Name: quarkusDataSourceDataIndexUserName, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: diQuarkusDataSource.SecretUserKey, - LocalObjectReference: diDBSecretRef, - }, - }, - }, - corev1.EnvVar{ - Name: quarkusDataSourceDataIndexPassword, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: diQuarkusDataSource.SecretPasswordKey, - LocalObjectReference: diDBSecretRef, - }, - }, - }, - corev1.EnvVar{ - Name: quarkusFlywayDataIndexSchemas, - Value: diQuarkusDataSource.Schema, - }) - } - - envVars = append(envVars, corev1.EnvVar{ - Name: migrateDBJobsService, - Value: strconv.FormatBool(dbmj.Data.MigrateDBJobsService), - }) - if dbmj.Data.MigrateDBJobsService { - envVars = append(envVars, - corev1.EnvVar{ - Name: quarkusDataSourceJobsServiceJdbcURL, - Value: jsQuarkusDataSource.JdbcUrl, - }, - corev1.EnvVar{ - Name: quarkusDataSourceJobsServiceUserName, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: jsQuarkusDataSource.SecretUserKey, - LocalObjectReference: jsDBSecretRef, - }, - }, - }, - corev1.EnvVar{ - Name: quarkusDataSourceJobsServicePassword, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: jsQuarkusDataSource.SecretPasswordKey, - LocalObjectReference: jsDBSecretRef, - }, - }, - }, - corev1.EnvVar{ - Name: quarkusFlywayJobsServiceSchemas, - Value: jsQuarkusDataSource.Schema, - }) - } - - job := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: dbMigrationJobCfg.JobName, - Namespace: platform.Namespace, - Labels: lbl, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: dbMigrationJobCfg.ContainerName, - Image: dbMigrationJobCfg.ToolImageName, - Env: envVars, - }, - }, - RestartPolicy: "Never", - }, - }, - BackoffLimit: pointer.Int32(0), - }, - } - return job -} - -// GetDBMigrationJobStatus Returns db migration job status -func (dbmj DBMigratorJob) GetDBMigrationJobStatus(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform) (*DBMigratorJobStatus, error) { - job, err := client.BatchV1().Jobs(platform.Namespace).Get(ctx, dbmj.Name, metav1.GetOptions{}) - if err != nil { - klog.V(log.E).InfoS("Error getting DB migrator job while monitoring completion: ", "error", err, "namespace", platform.Namespace, "job", job.Name) - return nil, err - } - return &DBMigratorJobStatus{job.Name, &job.Status}, nil -} - -// NewSonataFlowPlatformDBMigrationPhase Returns a new DB migration phase for SonataFlowPlatform -func NewSonataFlowPlatformDBMigrationPhase(status operatorapi.DBMigrationStatus, message string, reason string) *operatorapi.SonataFlowPlatformDBMigrationPhase { - return &operatorapi.SonataFlowPlatformDBMigrationPhase{ - Status: status, - Message: message, - Reason: reason, - } -} - -// UpdateSonataFlowPlatformDBMigrationPhase Updates a given SonataFlowPlatformDBMigrationPhase with the supplied values -func UpdateSonataFlowPlatformDBMigrationPhase(dbMigrationStatus *operatorapi.SonataFlowPlatformDBMigrationPhase, status operatorapi.DBMigrationStatus, message string, reason string) *operatorapi.SonataFlowPlatformDBMigrationPhase { - if dbMigrationStatus != nil { - dbMigrationStatus.Status = status - dbMigrationStatus.Message = message - dbMigrationStatus.Reason = reason - return dbMigrationStatus - } - return nil -} - -func getKogitoDBMigratorToolImageName() string { - - imgTag := cfg.GetCfg().DbMigratorToolImageTag - - if imgTag == "" { - // returns "docker.io/apache/incubator-kie-kogito-db-migrator-tool:" - imgTag = fmt.Sprintf("%s-%s:%s", constants.ImageNamePrefix, constants.KogitoDBMigratorTool, version.GetImageTagVersion()) - } - return imgTag -} - -func newDBMigrationJobCfg(name string) *DBMigrationJobCfg { - return &DBMigrationJobCfg{ - JobName: name, - ContainerName: dbMigrationContainerName, - ToolImageName: getKogitoDBMigratorToolImageName(), - } -} - -func hasFailed(dbMigratorJobStatus *DBMigratorJobStatus) bool { - return dbMigratorJobStatus.BatchJobStatus.Failed == dbMigrationJobFailed -} - -func hasSucceeded(dbMigratorJobStatus *DBMigratorJobStatus) bool { - return dbMigratorJobStatus.BatchJobStatus.Succeeded == dbMigrationJobSucceeded -} - -// ReconcileDBMigrationJob Check the status of running DB migration job and return status -func (dbmj DBMigratorJob) ReconcileDBMigrationJob(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform) (*DBMigratorJobStatus, error) { - platform.Status.SonataFlowPlatformDBMigrationPhase = NewSonataFlowPlatformDBMigrationPhase(operatorapi.DBMigrationStatusStarted, operatorapi.MessageDBMigrationStatusStarted, operatorapi.ReasonDBMigrationStatusStarted) - - dbMigratorJobStatus, err := dbmj.GetDBMigrationJobStatus(ctx, client, platform) - if err != nil { - return nil, err - } - - klog.V(log.I).InfoS("Db migration job status: ", "namespace", platform.Namespace, "job", dbMigratorJobStatus.Name, "active", dbMigratorJobStatus.BatchJobStatus.Active, "ready", dbMigratorJobStatus.BatchJobStatus.Ready, "failed", dbMigratorJobStatus.BatchJobStatus.Failed, "success", dbMigratorJobStatus.BatchJobStatus.Succeeded, "CompletedIndexes", dbMigratorJobStatus.BatchJobStatus.CompletedIndexes, "terminatedPods", dbMigratorJobStatus.BatchJobStatus.UncountedTerminatedPods) - - if hasFailed(dbMigratorJobStatus) { - platform.Status.SonataFlowPlatformDBMigrationPhase = UpdateSonataFlowPlatformDBMigrationPhase(platform.Status.SonataFlowPlatformDBMigrationPhase, operatorapi.DBMigrationStatusFailed, operatorapi.MessageDBMigrationStatusFailed, operatorapi.ReasonDBMigrationStatusFailed) - klog.V(log.I).InfoS("DB migration job failed", "namespace", platform.Namespace, "job", dbMigratorJobStatus.Name) - return dbMigratorJobStatus, errors.New("DB migration job failed. namespace=" + platform.Namespace + " job=" + dbMigratorJobStatus.Name) - } else if hasSucceeded(dbMigratorJobStatus) { - platform.Status.SonataFlowPlatformDBMigrationPhase = UpdateSonataFlowPlatformDBMigrationPhase(platform.Status.SonataFlowPlatformDBMigrationPhase, operatorapi.DBMigrationStatusSucceeded, operatorapi.MessageDBMigrationStatusSucceeded, operatorapi.ReasonDBMigrationStatusSucceeded) - klog.V(log.I).InfoS("DB migration job succeeded", "namespace", platform.Namespace, "job", dbMigratorJobStatus.Name) - } else { - // DB migration is still running - platform.Status.SonataFlowPlatformDBMigrationPhase = UpdateSonataFlowPlatformDBMigrationPhase(platform.Status.SonataFlowPlatformDBMigrationPhase, operatorapi.DBMigrationStatusInProgress, operatorapi.MessageDBMigrationStatusInProgress, operatorapi.ReasonDBMigrationStatusInProgress) - } - - return dbMigratorJobStatus, nil -} diff --git a/internal/controller/platform/db_migrator_job_test.go b/internal/controller/platform/db_migrator_job_test.go deleted file mode 100644 index 467eebdc..00000000 --- a/internal/controller/platform/db_migrator_job_test.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "fmt" - "hash/fnv" - "testing" - - "github.com/kubesmarts/logic-operator/api/version" - - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - "github.com/kubesmarts/logic-operator/test" -) - -const ( - DataIndexJdbcUrl = "jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service" - DefaultSchema = "default-schema" - DataIndexSchemaName = "data-index-service" - SonataFlowPlatformName = "db-migration-sonataflow-platform" - DBMigrationStrategyJob = "job" - DBSecretKeyRef = "dbSecretName" - UserNameKey = "postgresUserKey" - PasswordKey = "postgresPasswordKey" - DbMigrationContainerName = "db-migration-container" -) - -func getBaseSonataFlowPlatformInReadyPhase(namespace string) *v1alpha08.SonataFlowPlatform { - return test.GetBaseSonataFlowPlatformInReadyPhase(namespace) -} - -func TestDbMigratorJob(t *testing.T) { - t.Run("verify the sonataflow-platform first", func(t *testing.T) { - ksp := getBaseSonataFlowPlatformInReadyPhase(t.Name()) - assert.Equal(t, ksp.Name, SonataFlowPlatformName) - assert.Equal(t, ksp.Spec.Services.DataIndex.Persistence.DBMigrationStrategy, DBMigrationStrategyJob) - }) - - t.Run("verify data-index jdbc url", func(t *testing.T) { - ksp := getBaseSonataFlowPlatformInReadyPhase(t.Name()) - env := persistence.ConfigurePostgreSQLEnv(ksp.Spec.Services.DataIndex.Persistence.PostgreSQL, "data-index-schema", ksp.Namespace, false) - - jdbcUrl := getJdbcUrl(env) - assert.Equal(t, jdbcUrl, DataIndexJdbcUrl) - }) - - t.Run("verify new quarkus data source", func(t *testing.T) { - quarkusDataSource := newQuarkusDataSource(DataIndexJdbcUrl, DBSecretKeyRef, UserNameKey, PasswordKey, DataIndexSchemaName) - assert.Equal(t, quarkusDataSource.Schema, DataIndexSchemaName) - assert.Equal(t, quarkusDataSource.JdbcUrl, DataIndexJdbcUrl) - }) - - t.Run("verify new new db migration job config", func(t *testing.T) { - jobName, err := getDbMigratorJobName(version.GetImageTagVersion()) - assert.NoError(t, err) - versionHash := fnv.New32a() - _, err = versionHash.Write([]byte(version.GetImageTagVersion())) - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("sonataflow-db-migrator-job-%x", versionHash.Sum32()), jobName) - dbMigrationJobCfg := newDBMigrationJobCfg(jobName) - assert.Equal(t, dbMigrationJobCfg.JobName, jobName) - assert.Equal(t, dbMigrationJobCfg.ContainerName, DbMigrationContainerName) - }) -} diff --git a/internal/controller/platform/defaults.go b/internal/controller/platform/defaults.go deleted file mode 100644 index 6263c5f6..00000000 --- a/internal/controller/platform/defaults.go +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "runtime" - "time" - - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/yaml" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const defaultSonataFlowPlatformName = "sonataflow-platform" - -func CreateOrUpdateWithDefaults(ctx context.Context, p *operatorapi.SonataFlowPlatform, verbose bool) error { - // update missing fields in the resource - if p.Status.Cluster == "" || utils.IsOpenShift() { - p.Status.Cluster = operatorapi.PlatformClusterOpenShift - p.Spec.Build.Config.BuildStrategy = operatorapi.PlatformBuildStrategy - } - if p.Status.Cluster == "" || !utils.IsOpenShift() { - p.Status.Cluster = operatorapi.PlatformClusterKubernetes - p.Spec.Build.Config.BuildStrategy = operatorapi.OperatorBuildStrategy - } - - err := setPlatformDefaults(p, verbose) - if err != nil { - return err - } - - err = configureRegistry(ctx, p, verbose) - if err != nil { - return err - } - - if verbose && p.Spec.Build.Config.Timeout.Duration != 0 { - klog.V(log.I).InfoS("Maven Timeout set", "timeout", p.Spec.Build.Config.Timeout.Duration) - } - - return createPlatformIfNotExists(ctx, p) -} - -func setPlatformDefaults(p *operatorapi.SonataFlowPlatform, verbose bool) error { - if p.Spec.Build.Config.BuildStrategyOptions == nil { - klog.V(log.D).InfoS("SonataFlow Platform: setting publish strategy options", "namespace", p.Namespace) - p.Spec.Build.Config.BuildStrategyOptions = map[string]string{} - } - - if p.Spec.Build.Config.GetTimeout().Duration != 0 { - d := p.Spec.Build.Config.GetTimeout().Duration.Truncate(time.Second) - - if verbose && p.Spec.Build.Config.Timeout.Duration != d { - klog.V(log.I).InfoS("ContainerBuild timeout minimum unit is sec", "configured", p.Spec.Build.Config.GetTimeout().Duration, "truncated", d) - } - - klog.V(log.D).InfoS("SonataFlow Platform: setting build timeout", "namespace", p.Namespace) - p.Spec.Build.Config.Timeout = &metav1.Duration{ - Duration: d, - } - } else { - klog.V(log.D).InfoS("SonataFlow Platform setting default build timeout to 5 minutes", "namespace", p.Namespace) - p.Spec.Build.Config.Timeout = &metav1.Duration{ - Duration: 5 * time.Minute, - } - } - - if p.Spec.Build.Config.IsStrategyOptionEnabled(kanikoBuildCacheEnabled) { - p.Spec.Build.Config.BuildStrategyOptions[kanikoPVCName] = p.Name - if len(p.Spec.Build.Config.BaseImage) == 0 { - p.Spec.Build.Config.BaseImage = workflowdef.GetDefaultWorkflowBuilderImageTag() - } - } - - if p.Spec.Build.Config.BuildStrategy == operatorapi.OperatorBuildStrategy && !p.Spec.Build.Config.IsStrategyOptionEnabled(kanikoBuildCacheEnabled) { - // Default to disabling Kaniko cache warmer - // Using the cache warmer pod seems unreliable with the current Kaniko version - // and requires relying on a persistent volume. - defaultKanikoBuildCache := "false" - p.Spec.Build.Config.BuildStrategyOptions[kanikoBuildCacheEnabled] = defaultKanikoBuildCache - if verbose { - klog.V(log.I).InfoS("Kaniko cache set", "value", defaultKanikoBuildCache) - } - } - - // When dataIndex object set, default to enabled if bool not set - if p.Spec.Services != nil { - var enable = true - if p.Spec.Services.DataIndex != nil && p.Spec.Services.DataIndex.Enabled == nil { - p.Spec.Services.DataIndex.Enabled = &enable - } - // When the JobService field has a value, default to enabled if the `Enabled` field's value is nil - if p.Spec.Services.JobService != nil && p.Spec.Services.JobService.Enabled == nil { - p.Spec.Services.JobService.Enabled = &enable - } - } - setStatusAdditionalInfo(p) - - if verbose { - klog.V(log.I).InfoS("baseImage set", "value", p.Spec.Build.Config.BaseImage) - klog.V(log.I).InfoS("Timeout set", "value", p.Spec.Build.Config.GetTimeout()) - } - return nil -} - -func setStatusAdditionalInfo(platform *operatorapi.SonataFlowPlatform) { - platform.Status.Info = make(map[string]string) - - klog.V(log.D).InfoS("SonataFlow setting status info", "namespace", platform.Namespace) - platform.Status.Info["goVersion"] = runtime.Version() - platform.Status.Info["goOS"] = runtime.GOOS -} - -func configureRegistry(ctx context.Context, p *operatorapi.SonataFlowPlatform, verbose bool) error { - if p.Spec.Build.Config.BuildStrategy == operatorapi.PlatformBuildStrategy && p.Status.Cluster == operatorapi.PlatformClusterOpenShift { - p.Spec.Build.Config.Registry = operatorapi.RegistrySpec{} - klog.V(log.D).InfoS("Platform registry not set and ignored on openshift cluster") - return nil - } - - if p.Spec.Build.Config.Registry.Address == "" && p.Status.Cluster == operatorapi.PlatformClusterKubernetes { - // try KEP-1755 - address, err := getRegistryAddress(ctx) - if err != nil && verbose { - klog.V(log.E).ErrorS(err, "Cannot find a registry where to push images via KEP-1755") - } else if err == nil && address != nil { - p.Spec.Build.Config.Registry.Address = *address - } - } - - klog.V(log.D).InfoS("Final Registry Address", "address", p.Spec.Build.Config.Registry.Address) - return nil -} - -// getRegistryAddress KEP-1755 -// https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry -func getRegistryAddress(ctx context.Context) (*string, error) { - config := corev1.ConfigMap{} - err := utils.GetClient().Get(ctx, ctrl.ObjectKey{Namespace: "kube-public", Name: "local-registry-hosting"}, &config) - if err != nil { - if k8serrors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - if data, ok := config.Data["localRegistryHosting.v1"]; ok { - result := LocalRegistryHostingV1{} - if err := yaml.Unmarshal([]byte(data), &result); err != nil { - return nil, err - } - return &result.HostFromClusterNetwork, nil - } - return nil, nil -} - -func createPlatformIfNotExists(ctx context.Context, p *operatorapi.SonataFlowPlatform) error { - newPlt := operatorapi.SonataFlowPlatform{} - err := utils.GetClient().Get(ctx, ctrl.ObjectKey{Namespace: p.Namespace, Name: p.Name}, &newPlt) - if errors.IsNotFound(err) { - klog.V(log.D).ErrorS(err, "Platform not found, creating it") - return utils.GetClient().Create(ctx, p) - } - - // FIXME: We should never update the object within methods like this, but let the actual reconciler to do it - // https://github.com/kubesmarts/logic-operator/issues/538 - if err = SafeUpdatePlatformStatus(ctx, p); err != nil { - klog.V(log.E).ErrorS(err, "Error updating the platform status") - return err - } - - // FIXME: We should never update the object within methods like this, but let the actual reconciler to do it - // https://github.com/kubesmarts/logic-operator/issues/538 - if err = SafeUpdatePlatform(ctx, p); err != nil { - klog.V(log.E).ErrorS(err, "Error updating the platform") - return err - } - return nil -} diff --git a/internal/controller/platform/initialize.go b/internal/controller/platform/initialize.go deleted file mode 100644 index fe0c776c..00000000 --- a/internal/controller/platform/initialize.go +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api" - - "github.com/kubesmarts/logic-operator/api/metadata" - - "github.com/kubesmarts/logic-operator/container-builder/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -const ( - defaultKanikoCachePVCName = "kogito-kaniko-cache-pv" -) - -// NewInitializeAction returns an action that initializes the platform configuration when not provided by the user. -func NewInitializeAction() Action { - return &initializeAction{} -} - -type initializeAction struct { - baseAction -} - -func (action *initializeAction) Name() string { - return "initialize" -} - -func (action *initializeAction) CanHandle(platform *operatorapi.SonataFlowPlatform) bool { - return platform.Status.GetTopLevelCondition().IsUnknown() || platform.Status.IsDuplicated() -} - -func (action *initializeAction) Handle(ctx context.Context, platform *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, *corev1.Event, error) { - duplicate, err := action.isPrimaryDuplicate(ctx, platform) - if err != nil { - return nil, nil, err - } - if duplicate { - // another platform already present in the namespace - if !platform.Status.IsDuplicated() { - plat := platform.DeepCopy() - plat.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformDuplicatedReason, "") - return plat, nil, nil - } - - return nil, nil, nil - } - - if err = CreateOrUpdateWithDefaults(ctx, platform, true); err != nil { - return nil, nil, err - } - // nolint: staticcheck - if platform.Spec.Build.Config.BuildStrategy == operatorapi.OperatorBuildStrategy { - //If KanikoCache is enabled - if IsKanikoCacheEnabled(platform) { - // Create the persistent volume claim used by the Kaniko cache - klog.V(log.I).InfoS("Create persistent volume claim") - err := createPersistentVolumeClaim(ctx, action.client, platform) - if err != nil { - return nil, nil, err - } - // Create the Kaniko warmer pod that caches the base image into the SonataFlow builder volume - klog.V(log.I).InfoS("Create Kaniko cache warmer pod") - err = createKanikoCacheWarmerPod(ctx, action.client, platform) - if err != nil { - return nil, nil, err - } - platform.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformWarmingReason, "") - } else { - // Skip the warmer pod creation - platform.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformCreatingReason, "") - } - } else { - platform.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformCreatingReason, "") - } - platform.Status.Version = metadata.SpecVersion - - return platform, nil, nil -} - -// TODO: move this to Kaniko packages based on the platform context - -func createPersistentVolumeClaim(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform) error { - volumeSize, err := resource.ParseQuantity(cfg.GetCfg().DefaultPvcKanikoSize) - if err != nil { - return err - } - // nolint: staticcheck - pvcName := defaultKanikoCachePVCName - if persistentVolumeClaim, found := platform.Spec.Build.Config.BuildStrategyOptions[kanikoPVCName]; found { - pvcName = persistentVolumeClaim - } - - pvc := &corev1.PersistentVolumeClaim{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "PersistentVolumeClaim", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: platform.Namespace, - Name: pvcName, - Labels: map[string]string{ - "app": "kogito-serverless-operator", - }, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.ReadWriteOnce, - }, - Resources: corev1.VolumeResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: volumeSize, - }, - }, - }, - } - - err = client.Create(ctx, pvc) - // Skip the error in case the PVC already exists - if err != nil && !k8serrors.IsAlreadyExists(err) { - return err - } - - return nil -} - -// Function to double-check if there is already an active platform on the current context (i.e. namespace) -func (action *initializeAction) isPrimaryDuplicate(ctx context.Context, thisPlatform *operatorapi.SonataFlowPlatform) (bool, error) { - if IsSecondary(thisPlatform) { - // Always reconcile secondary platforms - return false, nil - } - platforms, err := listPrimaryPlatforms(ctx, action.client, thisPlatform.Namespace) - if err != nil { - return false, err - } - for _, p := range platforms.Items { - p := p // pin - if p.Name != thisPlatform.Name && IsActive(&p) { - return true, nil - } - } - - return false, nil -} diff --git a/internal/controller/platform/k8s.go b/internal/controller/platform/k8s.go deleted file mode 100644 index fdfae122..00000000 --- a/internal/controller/platform/k8s.go +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "fmt" - - v2 "k8s.io/api/autoscaling/v2" - policyv1 "k8s.io/api/policy/v1" - - "github.com/kubesmarts/logic-operator/api/version" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/api/metadata" - - "github.com/imdario/mergo" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/variables" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -// NewServiceAction returns an action that deploys the services. -func NewServiceAction() Action { - return &serviceAction{} -} - -type serviceAction struct { - baseAction -} - -func (action *serviceAction) Name() string { - return "service" -} - -func (action *serviceAction) CanHandle(platform *operatorapi.SonataFlowPlatform) bool { - return platform.Status.IsReady() -} - -func (action *serviceAction) Handle(ctx context.Context, platform *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, *corev1.Event, error) { - // Refresh applied configuration - if err := CreateOrUpdateWithDefaults(ctx, platform, false); err != nil { - return nil, nil, err - } - - psDI := services.NewDataIndexHandler(platform) - psJS := services.NewJobServiceHandler(platform) - - if IsJobsBasedDBMigration(platform, psDI, psJS) { - p, err := HandleDBMigrationJob(ctx, action.client, platform, psDI, psJS) - if p == nil && err == nil { // DB migration is in-progress - return nil, nil, nil - } else if p == nil && err != nil { // DB migration failed - klog.V(log.E).ErrorS(err, "Error handling DB migration job", "namespace", platform.Namespace) - return nil, nil, err - } - } - - if psDI.IsServiceSetInSpec() { - if event, err := createOrUpdateServiceComponents(ctx, action.client, platform, psDI); err != nil { - return nil, event, err - } - } - - if psJS.IsServiceSetInSpec() { - if event, err := createOrUpdateServiceComponents(ctx, action.client, platform, psJS); err != nil { - return nil, event, err - } - } - - return platform, nil, nil -} - -func createOrUpdateServiceComponents(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) (*corev1.Event, error) { - var deployment *appsv1.Deployment - var hpa *v2.HorizontalPodAutoscaler - var err error - if err = createOrUpdateConfigMap(ctx, client, platform, psh); err != nil { - return nil, err - } - if deployment, hpa, err = createOrUpdateDeployment(ctx, client, platform, psh); err != nil { - return nil, err - } - if err = createOrUpdatePDB(ctx, client, platform, psh, deployment, hpa); err != nil { - return nil, err - } - if err = createOrUpdateService(ctx, client, platform, psh); err != nil { - return nil, err - } - return createOrUpdateKnativeResources(ctx, client, platform, psh) -} - -func createOrUpdateDeployment(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) (*appsv1.Deployment, *v2.HorizontalPodAutoscaler, error) { - readyProbe := &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: constants.QuarkusHealthPathReady, - Port: variables.DefaultHTTPWorkflowPortIntStr, - Scheme: corev1.URISchemeHTTP, - }, - }, - InitialDelaySeconds: int32(45), - TimeoutSeconds: int32(10), - PeriodSeconds: int32(30), - SuccessThreshold: int32(1), - FailureThreshold: int32(4), - } - liveProbe := readyProbe.DeepCopy() - liveProbe.ProbeHandler.HTTPGet.Path = constants.QuarkusHealthPathLive - imageTag := psh.GetServiceImageName(constants.PersistenceTypeEphemeral) - serviceContainer := &corev1.Container{ - Image: imageTag, - ImagePullPolicy: kubeutil.GetImagePullPolicy(imageTag), - Env: psh.GetEnvironmentVariables(), - Resources: psh.GetPodResourceRequirements(), - ReadinessProbe: readyProbe, - LivenessProbe: liveProbe, - Ports: []corev1.ContainerPort{ - { - Name: utils.DefaultServicePortName, - ContainerPort: int32(constants.DefaultHTTPWorkflowPortInt), - Protocol: corev1.ProtocolTCP, - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "application-config", - MountPath: "/home/kogito/config", - }, - }, - } - serviceContainer = psh.ConfigurePersistence(serviceContainer) - serviceContainer, err := psh.MergeContainerSpec(serviceContainer) - if err != nil { - return nil, nil, err - } - - // immutable - serviceContainer.Name = psh.GetContainerName() - - var hpa *v2.HorizontalPodAutoscaler = nil - if psh.AcceptsHPA() { - hpa, err = kubeutil.FindHPAForDeployment(ctx, utils.GetClient(), platform.Namespace, psh.GetServiceName()) - if err != nil { - return nil, nil, fmt.Errorf("failed to find a potential HorizontalPodAutoscaler for deployment %s/%s: %v", platform.Namespace, psh.GetServiceName(), err) - } - klog.V(log.D).Infof("HorizontalPodAutoscaler exists for deployment %s/%s: %t.", platform.Namespace, psh.GetServiceName(), hpa != nil) - } - kSinkInjected, err := psh.CheckKSinkInjected() - if err != nil { - return nil, nil, err - } - lbl, selectorLbl := getLabels(platform, psh) - serviceDeploymentSpec := appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: selectorLbl, - }, - Strategy: psh.GetDeploymentStrategy(), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: lbl, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: "application-config", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: psh.GetServiceCmName(), - }, - }, - }, - }, - }, - }, - }, - } - - serviceDeploymentSpec.Template.Spec, err = psh.MergePodSpec(serviceDeploymentSpec.Template.Spec) - if err != nil { - return nil, nil, err - } - kubeutil.AddOrReplaceContainer(serviceContainer.Name, *serviceContainer, &serviceDeploymentSpec.Template.Spec) - - serviceDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: platform.Namespace, - Name: psh.GetServiceName(), - Labels: lbl, - }} - if err := controllerutil.SetControllerReference(platform, serviceDeployment, client.Scheme()); err != nil { - return nil, nil, err - } - - // Create or Update the deployment - if op, err := controllerutil.CreateOrUpdate(ctx, client, serviceDeployment, func() error { - knative.SaveKnativeData(&serviceDeploymentSpec.Template.Spec, &serviceDeployment.Spec.Template.Spec) - err := mergo.Merge(&(serviceDeployment.Spec), serviceDeploymentSpec, mergo.WithOverride) - // mergo.Merge algorithm is not setting the serviceDeployment.Spec.Replicas when the - // *serviceDeploymentSpec.Replicas is 0. Making impossible to scale to zero. Ensure the value. - if hpa == nil || !kubeutil.HPAIsWorking(hpa) || psh.GetReplicaCount() == 0 { - // Only when no HorizontalPodAutoscaler was created for current deployment, we should manage the replicas. - // Or, when the existing one did not wake up from a previous inactive period due to a replicas set to 0. - // In this last case, we should still let the controller the chance to set the replicas to wake up the HorizontalPodAutoscaler. - // Or, when the user voluntary wants to set the replicas to 0. - replicas := psh.GetReplicaCount() - if !kSinkInjected { - replicas = 0 // Wait for K_SINK injection - } - serviceDeployment.Spec.Replicas = &replicas - } - if err != nil { - return err - } - return nil - }); err != nil { - return nil, nil, err - } else { - klog.V(log.I).InfoS("Deployment successfully reconciled", "operation", op) - } - return serviceDeployment, hpa, nil -} - -func createOrUpdatePDB(ctx context.Context, c client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler, deployment *appsv1.Deployment, hpa *v2.HorizontalPodAutoscaler) error { - if psh.AcceptsPDB() { - createOrUpdate := false - pdbSpec := psh.GetPDBSpec() - if !kubeutil.IsEmptyPodDisruptionBudgetSpec(pdbSpec) { - if hpa != nil { - // The HPA determines the replicas. Be sure that the service can't be later downscaled to a number of replicas that blocks a drain. - // And also, that the user didn't voluntary scaled the service to 0. - createOrUpdate = kubeutil.HPAMinReplicasIsGreaterThan(hpa, int32(1)) && !kubeutil.DeploymentIsScaledToZero(deployment) - } else { - // The just reconciled deployment replicas were already configured properly, we can rely on this number. - // Be sure that the number of replicas don't block a drain. - createOrUpdate = kubeutil.DeploymentReplicasIsGreaterThan(deployment, int32(1)) - } - } - - if createOrUpdate { - lbl, selectorLbl := getLabels(platform, psh) - podDisruptionBudget := &policyv1.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Name: psh.GetServiceName(), - Namespace: platform.Namespace, - Labels: lbl, - }, - } - if err := controllerutil.SetControllerReference(platform, podDisruptionBudget, c.Scheme()); err != nil { - return err - } - if op, err := controllerutil.CreateOrUpdate(ctx, c, podDisruptionBudget, func() error { - kubeutil.ApplyPodDisruptionBudgetSpec(podDisruptionBudget, pdbSpec) - podDisruptionBudget.Spec.Selector = &metav1.LabelSelector{ - MatchLabels: selectorLbl, - } - return nil - }); err != nil { - return err - } else { - klog.V(log.I).Infof("PodDisruptionBudget %s/%s successfully reconciled, op: %s.", podDisruptionBudget.Namespace, podDisruptionBudget.Name, op) - } - } else { - // Delete a potentially existing PDB. - if err := kubeutil.SafeDeletePodDisruptionBudget(ctx, c, platform.Namespace, psh.GetServiceName()); err != nil { - return err - } - } - } - return nil -} - -func createOrUpdateService(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) error { - lbl, selectorLbl := getLabels(platform, psh) - dataSvcSpec := corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - { - Name: utils.DefaultServicePortName, - Protocol: corev1.ProtocolTCP, - Port: 80, - TargetPort: variables.DefaultHTTPWorkflowPortIntStr, - }, - }, - Selector: selectorLbl, - } - dataSvc := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: platform.Namespace, - Name: psh.GetServiceName(), - Labels: lbl, - }} - if err := controllerutil.SetControllerReference(platform, dataSvc, client.Scheme()); err != nil { - return err - } - - // Create or Update the service - if op, err := controllerutil.CreateOrUpdate(ctx, client, dataSvc, func() error { - dataSvc.Spec = dataSvcSpec - - return nil - }); err != nil { - return err - } else { - klog.V(log.I).InfoS("Service successfully reconciled", "operation", op) - } - - return nil -} - -// getServicesLabelsMap A common utility function for use by SonataFlow Services (e.g. DI/JS and DB Migrator) to obtain standard common labels by passing parameters -func getServicesLabelsMap(app string, appNamespace string, service string, k8sName string, k8sComponent string, k8sPartOf string, k8sManagedBy string) (map[string]string, map[string]string) { - lbl := map[string]string{ - workflowproj.LabelApp: app, - workflowproj.LabelAppNamespace: appNamespace, - workflowproj.LabelService: service, - metadata.KubernetesLabelInstance: app, - metadata.KubernetesLabelName: k8sName, - metadata.KubernetesLabelComponent: k8sComponent, - metadata.KubernetesLabelPartOf: k8sPartOf, - metadata.KubernetesLabelManagedBy: k8sManagedBy, - metadata.KubernetesLabelVersion: version.GetImageTagVersion(), - } - - selectorLbl := map[string]string{ - workflowproj.LabelService: service, - } - - return lbl, selectorLbl -} - -// getLabels Specifically used by services implementing services.PlatformServiceHandler interface such as DI/JS -func getLabels(platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) (map[string]string, map[string]string) { - return getServicesLabelsMap(platform.Name, platform.Namespace, psh.GetServiceName(), psh.GetContainerName(), psh.GetServiceName(), platform.Name, "sonataflow-operator") -} - -func createOrUpdateConfigMap(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) error { - handler, err := services.NewServiceAppPropertyHandler(psh) - if err != nil { - return err - } - lbl, _ := getLabels(platform, psh) - dataStr := handler.Build() - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: psh.GetServiceCmName(), - Namespace: platform.Namespace, - Labels: lbl, - }, - Data: map[string]string{ - workflowproj.ApplicationPropertiesFileName: dataStr, - }, - } - if err := controllerutil.SetControllerReference(platform, configMap, client.Scheme()); err != nil { - return err - } - - // Create or Update the service - if op, err := controllerutil.CreateOrUpdate(ctx, client, configMap, func() error { - configMap.Data[workflowproj.ApplicationPropertiesFileName] = handler.WithUserProperties(dataStr).Build() - - return nil - }); err != nil { - return err - } else { - klog.V(log.I).InfoS("ConfigMap successfully reconciled", "operation", op) - } - return nil -} - -func setSonataFlowPlatformFinalizer(ctx context.Context, c client.Client, platform *operatorapi.SonataFlowPlatform) error { - if !controllerutil.ContainsFinalizer(platform, constants.TriggerFinalizer) { - controllerutil.AddFinalizer(platform, constants.TriggerFinalizer) - return c.Update(ctx, platform) - } - return nil -} - -func createOrUpdateKnativeResources(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) (*corev1.Event, error) { - lbl, _ := getLabels(platform, psh) - objs, event, err := psh.GenerateKnativeResources(platform, lbl) - if err != nil { - return event, err - } - // Create or update triggers - for _, obj := range objs { - if triggerDef, ok := obj.(*eventingv1.Trigger); ok { - if platform.Namespace == obj.GetNamespace() { - if err := controllerutil.SetControllerReference(platform, obj, client.Scheme()); err != nil { - return nil, err - } - } else { - // This is for Knative trigger in a different namespace - // Set the finalizer for trigger cleanup when the platform is deleted - if err := setSonataFlowPlatformFinalizer(ctx, client, platform); err != nil { - return nil, err - } - } - trigger := &eventingv1.Trigger{ - ObjectMeta: triggerDef.ObjectMeta, - } - _, err := controllerutil.CreateOrUpdate(ctx, client, trigger, func() error { - trigger.Spec = triggerDef.Spec - return nil - }) - if err != nil { - return nil, err - } - addToSonataFlowPlatformTriggerList(platform, trigger) - } - } - - if err := SafeUpdatePlatformStatus(ctx, platform); err != nil { - return nil, err - } - - // Create or update sinkbindings - for _, obj := range objs { - if sbDef, ok := obj.(*sourcesv1.SinkBinding); ok { - if err := controllerutil.SetControllerReference(platform, obj, client.Scheme()); err != nil { - return nil, err - } - sinkBinding := &sourcesv1.SinkBinding{ - ObjectMeta: sbDef.ObjectMeta, - } - _, err = controllerutil.CreateOrUpdate(ctx, client, sinkBinding, func() error { - sinkBinding.Spec = sbDef.Spec - return nil - }) - if err != nil { - return nil, err - } - kSinkInjected, err := psh.CheckKSinkInjected() - if err != nil { - return nil, err - } - if !kSinkInjected { - msg := fmt.Sprintf("waiting for K_SINK injection for service %s to complete", psh.GetServiceName()) - event := &corev1.Event{ - Type: corev1.EventTypeWarning, - Reason: services.WaitingKnativeEventing, - Message: msg, - } - return event, fmt.Errorf("%s", msg) - } - } - } - return nil, nil -} - -func addToSonataFlowPlatformTriggerList(platform *operatorapi.SonataFlowPlatform, trigger *eventingv1.Trigger) { - for _, t := range platform.Status.Triggers { - if t.Name == trigger.Name && t.Namespace == trigger.Namespace { - return // trigger already exists - } - } - platform.Status.Triggers = append(platform.Status.Triggers, operatorapi.SonataFlowPlatformTriggerRef{Name: trigger.Name, Namespace: trigger.Namespace}) -} diff --git a/internal/controller/platform/kaniko_cache.go b/internal/controller/platform/kaniko_cache.go deleted file mode 100644 index 77ef058a..00000000 --- a/internal/controller/platform/kaniko_cache.go +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - v08 "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/client" -) - -// kanikoCacheDir is the cache directory for Kaniko builds (mounted into the Kaniko pod). -const ( - kanikoCacheDir = "/kaniko/cache" - kanikoPVCName = "KanikoPersistentVolumeClaim" - kanikoWarmerImage = "KanikoWarmerImage" - kanikoBuildCacheEnabled = "KanikoBuildCacheEnabled" -) - -func IsKanikoCacheEnabled(platform *v08.SonataFlowPlatform) bool { - return platform.Spec.Build.Config.IsStrategyOptionEnabled(kanikoBuildCacheEnabled) -} - -func createKanikoCacheWarmerPod(ctx context.Context, client client.Client, platform *v08.SonataFlowPlatform) error { - // The pod will be scheduled to nodes that are selected by the persistent volume - // node affinity spec, if any, as provisioned by the persistent volume claim storage - // class provisioner. - // See: - // - https://kubernetes.io/docs/concepts/storage/persistent-volumes/#node-affinity - // - https://kubernetes.io/docs/concepts/storage/volumes/#local - // nolint: staticcheck - pvcName := defaultKanikoCachePVCName - if persistentVolumeClaim, found := platform.Spec.Build.Config.BuildStrategyOptions[kanikoPVCName]; found { - pvcName = persistentVolumeClaim - } - - var warmerImage string - if image, found := platform.Spec.Build.Config.BuildStrategyOptions[kanikoWarmerImage]; found { - warmerImage = image - } else { - warmerImage = cfg.GetCfg().KanikoDefaultWarmerImageTag - } - - pod := corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: platform.Namespace, - Name: platform.Name + "-cache", - Labels: map[string]string{ - "sonataflow.org/component": "kaniko-warmer", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "warm-kaniko-cache", - Image: warmerImage, - Args: []string{ - "--force", - "--cache-dir=" + kanikoCacheDir, - "--image=" + platform.Spec.Build.Config.BaseImage, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "kaniko-cache", - MountPath: kanikoCacheDir, - }, - }, - /* TODO: enable this test once we apply security enforcement: https://issues.redhat.com/browse/KOGITO-8799 - SecurityContext: kubeutil.SecurityDefaults(),*/ - }, - }, - // Create the cache directory otherwise Kaniko warmer skips caching silently - InitContainers: []corev1.Container{ - { - Name: "create-kaniko-cache", - Image: "busybox", - ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{"/bin/sh", "-c"}, - Args: []string{"mkdir -p " + kanikoCacheDir + "&& chmod -R a+rwx " + kanikoCacheDir}, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "kaniko-cache", - MountPath: kanikoCacheDir, - }, - }, - /* TODO: enable this test once we apply security enforcement: https://issues.redhat.com/browse/KOGITO-8799 - SecurityContext: kubeutil.SecurityDefaults(),*/ - }, - }, - RestartPolicy: corev1.RestartPolicyOnFailure, - Volumes: []corev1.Volume{ - { - Name: "kaniko-cache", - VolumeSource: corev1.VolumeSource{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvcName, - }, - }, - }, - }, - }, - } - - err := client.Delete(ctx, &pod) - if err != nil && !k8serrors.IsNotFound(err) { - return errors.Wrap(err, "cannot delete Kaniko warmer pod") - } - - err = client.Create(ctx, &pod) - if err != nil { - return errors.Wrap(err, "cannot create Kaniko warmer pod") - } - - return nil -} diff --git a/internal/controller/platform/monitor.go b/internal/controller/platform/monitor.go deleted file mode 100644 index 717247d8..00000000 --- a/internal/controller/platform/monitor.go +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -// NewMonitorAction returns an action that monitors the build platform after it's fully initialized. -func NewMonitorAction() Action { - return &monitorAction{} -} - -type monitorAction struct { - baseAction -} - -func (action *monitorAction) Name() string { - return "monitor" -} - -func (action *monitorAction) CanHandle(platform *operatorapi.SonataFlowPlatform) bool { - return platform.Status.IsReady() -} - -func (action *monitorAction) Handle(ctx context.Context, platform *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, *corev1.Event, error) { - // Just track the version of the operator in the platform resource - if platform.Status.Version != metadata.SpecVersion { - platform.Status.Version = metadata.SpecVersion - klog.V(log.I).InfoS("Platform version updated", "version", platform.Status.Version) - } - - // Refresh applied configuration - if err := CreateOrUpdateWithDefaults(ctx, platform, false); err != nil { - return nil, nil, err - } - - return platform, nil, nil -} diff --git a/internal/controller/platform/platform.go b/internal/controller/platform/platform.go deleted file mode 100644 index 8e05df48..00000000 --- a/internal/controller/platform/platform.go +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "fmt" - "os" - "strings" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/klog/v2" - - coordination "k8s.io/api/coordination/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - - "github.com/kubesmarts/logic-operator/log" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/utils" -) - -const ( - // DefaultPlatformName is the standard name used for the platform. - DefaultPlatformName = "kogito-serverless-platform" - - OperatorWatchNamespaceEnvVariable = "WATCH_NAMESPACE" - operatorNamespaceEnvVariable = "NAMESPACE" -) - -// Copied from https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry - -// LocalRegistryHostingV1 describes a local registry that developer tools can -// connect to. A local registry allows clients to load images into the local -// cluster by pushing to this registry. -type LocalRegistryHostingV1 struct { - // Host documents the host (hostname and port) of the registry, as seen from - // outside the cluster. - // - // This is the registry host that tools outside the cluster should push images - // to. - Host string `yaml:"host,omitempty"` - - // HostFromClusterNetwork documents the host (hostname and port) of the - // registry, as seen from networking inside the container pods. - // - // This is the registry host that tools running on pods inside the cluster - // should push images to. If not set, then tools inside the cluster should - // assume the local registry is not available to them. - HostFromClusterNetwork string `yaml:"hostFromClusterNetwork,omitempty"` - - // HostFromContainerRuntime documents the host (hostname and port) of the - // registry, as seen from the cluster's container runtime. - // - // When tools apply Kubernetes objects to the cluster, this host should be - // used for image name fields. If not set, users of this field should use the - // value of Host instead. - // - // Note that it doesn't make sense semantically to define this field, but not - // define Host or HostFromClusterNetwork. That would imply a way to pull - // images without a way to push images. - HostFromContainerRuntime string `yaml:"hostFromContainerRuntime,omitempty"` - - // Help contains a URL pointing to documentation for users on how to set - // up and configure a local registry. - // - // Tools can use this to nudge users to enable the registry. When possible, - // the writer should use as permanent a URL as possible to prevent drift - // (e.g., a version control SHA). - // - // When image pushes to a registry host specified in one of the other fields - // fail, the tool should display this help URL to the user. The help URL - // should contain instructions on how to diagnose broken or misconfigured - // registries. - Help string `yaml:"help,omitempty"` -} - -const OperatorLockName = "kogito-serverless-lock" - -// IsCurrentOperatorGlobal returns true if the operator is configured to watch all namespaces. -func IsCurrentOperatorGlobal() bool { - if watchNamespace, envSet := os.LookupEnv(OperatorWatchNamespaceEnvVariable); !envSet || strings.TrimSpace(watchNamespace) == "" { - return true - } - return false -} - -// GetOperatorNamespace returns the namespace where the current operator is located (if set). -func GetOperatorNamespace() string { - if podNamespace, envSet := os.LookupEnv(operatorNamespaceEnvVariable); envSet { - return podNamespace - } - return "" -} - -// GetOperatorLockName returns the name of the lock lease that is electing a leader on the particular namepsace. -func GetOperatorLockName(operatorID string) string { - return fmt.Sprintf("%s-lock", operatorID) -} - -// GetActivePlatform returns the currently installed active platform in the local namespace. -// The parameter createIfNotExists determines if such platform must be created when not exists. Never nil when -// createsIfNotExists is true, unless an error. -func GetActivePlatform(ctx context.Context, c ctrl.Client, namespace string, createIfNotExists bool) (*operatorapi.SonataFlowPlatform, error) { - platform, err := getLocalPlatform(ctx, c, namespace, true) - if err != nil { - return nil, err - } - if platform != nil { - return platform, nil - } - klog.V(log.I).InfoS("No active SonataFlowPlatform was found in namespace", "Namespace", namespace) - if createIfNotExists { - klog.V(log.I).InfoS("Creating a default SonataFlowPlatform", "Namespace", namespace) - sfp := newEmptySonataFlowPlatform(namespace) - if err = CreateOrUpdateWithDefaults(ctx, sfp, false); err != nil { - return nil, err - } - return sfp, nil - } - return nil, nil -} - -// getLocalPlatform returns the currently installed active platform, or any platform, existing in local namespace when no -// active platform exists. When the active parameter is true, only active platforms are considered. -// In other cases, a non-active platform might be returned as a second option. -func getLocalPlatform(ctx context.Context, c ctrl.Client, namespace string, active bool) (*operatorapi.SonataFlowPlatform, error) { - klog.V(log.D).InfoS("Finding available platforms in namespace", "namespace", namespace) - lst, err := listPrimaryPlatforms(ctx, c, namespace) - if err != nil { - return nil, err - } - for _, p := range lst.Items { - platform := p // pin - if IsActive(&platform) { - klog.V(log.D).InfoS("Found active local platform", "platform", platform.Name) - return &platform, nil - } - } - - if !active && len(lst.Items) > 0 { - // does not require the platform to be active, just return one if present - res := lst.Items[0] - klog.V(log.D).InfoS("Found non-active local platform", "platform", res.Name) - return &res, nil - } - return nil, nil -} - -func newEmptySonataFlowPlatform(namespace string) *operatorapi.SonataFlowPlatform { - if utils.IsOpenShift() { - return &operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, - Spec: operatorapi.SonataFlowPlatformSpec{ - Build: operatorapi.BuildPlatformSpec{ - Config: operatorapi.BuildPlatformConfig{ - BuildStrategy: operatorapi.PlatformBuildStrategy, - }, - }, - }, - } - } - - return &operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, - Spec: operatorapi.SonataFlowPlatformSpec{ - Build: operatorapi.BuildPlatformSpec{ - Config: operatorapi.BuildPlatformConfig{ - BuildStrategyOptions: map[string]string{ - kanikoBuildCacheEnabled: "true", - }, - }, - }, - }, - } -} - -// listPrimaryPlatforms returns all non-secondary platforms installed in a given namespace (only one will be active). -func listPrimaryPlatforms(ctx context.Context, c ctrl.Reader, namespace string) (*operatorapi.SonataFlowPlatformList, error) { - lst, err := listAllPlatforms(ctx, c, namespace) - if err != nil { - return nil, err - } - - filtered := &operatorapi.SonataFlowPlatformList{} - for i := range lst.Items { - pl := lst.Items[i] - if !IsSecondary(&pl) { - filtered.Items = append(filtered.Items, pl) - } - } - return filtered, nil -} - -// listAllPlatforms returns all platforms installed in a given namespace. -func listAllPlatforms(ctx context.Context, c ctrl.Reader, namespace string) (*operatorapi.SonataFlowPlatformList, error) { - lst := operatorapi.NewSonataFlowPlatformList() - if err := c.List(ctx, &lst, ctrl.InNamespace(namespace)); err != nil { - return nil, err - } - return &lst, nil -} - -// IsActive determines if the given platform is being used. -func IsActive(p *operatorapi.SonataFlowPlatform) bool { - return !p.Status.IsDuplicated() -} - -// IsSecondary determines if the given platform is marked as secondary. -func IsSecondary(p *operatorapi.SonataFlowPlatform) bool { - if l, ok := p.Annotations[metadata.SecondaryPlatformAnnotation]; ok && l == "true" { - return true - } - return false -} - -// IsNamespaceLocked tells if the namespace contains a lock indicating that an operator owns it. -func IsNamespaceLocked(ctx context.Context, c ctrl.Reader, namespace string) (bool, error) { - if namespace == "" { - return false, nil - } - - platforms, err := listPrimaryPlatforms(ctx, c, namespace) - if err != nil { - return true, err - } - - for _, platform := range platforms.Items { - lease := coordination.Lease{} - - var operatorLockName string - if platform.Name != "" { - operatorLockName = GetOperatorLockName(platform.Name) - } else { - operatorLockName = OperatorLockName - } - - if err := c.Get(ctx, ctrl.ObjectKey{Namespace: namespace, Name: operatorLockName}, &lease); err == nil || !k8serrors.IsNotFound(err) { - return true, err - } - } - - return false, nil -} - -// IsOperatorAllowedOnNamespace returns true if the current operator is allowed to react on changes in the given namespace. -func IsOperatorAllowedOnNamespace(ctx context.Context, c ctrl.Reader, namespace string) (bool, error) { - // allow all local operators - if !IsCurrentOperatorGlobal() { - return true, nil - } - - // allow global operators that use a proper operator id - if utils.OperatorID() != "" { - return true, nil - } - - operatorNamespace := GetOperatorNamespace() - if operatorNamespace == namespace { - // Global operator is allowed on its own namespace - return true, nil - } - alreadyOwned, err := IsNamespaceLocked(ctx, c, namespace) - if err != nil { - return false, err - } - return !alreadyOwned, nil -} - -// IsOperatorHandler Operators matching the annotation operator id are allowed to reconcile. -// For legacy resources that are missing a proper operator id annotation the default global operator or the local -// operator in this namespace are candidates for reconciliation. -func IsOperatorHandler(object ctrl.Object) bool { - if object == nil { - return true - } - resourceID := utils.GetOperatorIDAnnotation(object) - operatorID := utils.OperatorID() - - // allow operator with matching id to handle the resource - if resourceID == operatorID { - return true - } - - // check if we are dealing with resource that is missing a proper operator id annotation - if resourceID == "" { - // allow default global operator to handle legacy resources (missing proper operator id annotations) - if operatorID == DefaultPlatformName { - return true - } - - // allow local operators to handle legacy resources (missing proper operator id annotations) - if !IsCurrentOperatorGlobal() { - return true - } - } - - return false -} - -// IsOperatorHandlerConsideringLock uses normal IsOperatorHandler checks and adds additional check for legacy resources -// that are missing a proper operator id annotation. In general two kind of operators race for reconcile these legacy resources. -// The local operator for this namespace and the default global operator instance. Based on the existence of a namespace -// lock the current local operator has precedence. When no lock exists the default global operator should reconcile. -func IsOperatorHandlerConsideringLock(ctx context.Context, c ctrl.Reader, namespace string, object ctrl.Object) bool { - isHandler := IsOperatorHandler(object) - if !isHandler { - return false - } - - resourceID := utils.GetOperatorIDAnnotation(object) - // add additional check on resources missing an operator id - if resourceID == "" { - operatorNamespace := GetOperatorNamespace() - if operatorNamespace == namespace { - // Global operator is allowed on its own namespace - return true - } - - if locked, err := IsNamespaceLocked(ctx, c, namespace); err != nil || locked { - // namespace is locked so local operators do have precedence - return !IsCurrentOperatorGlobal() - } - } - - return true -} diff --git a/internal/controller/platform/platformutils.go b/internal/controller/platform/platformutils.go deleted file mode 100644 index ea0fa884..00000000 --- a/internal/controller/platform/platformutils.go +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "regexp" - "strings" - - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/util/retry" - - "github.com/kubesmarts/logic-operator/utils" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -var builderDockerfileFromRE = regexp.MustCompile(`FROM (.*) AS builder`) - -// ResourceCustomizer can be used to inject code that changes the objects before they are created. -type ResourceCustomizer func(object ctrl.Object) ctrl.Object - -// GetCustomizedBuilderDockerfile determines if the default Dockerfile provided by the -// sonataflow-operator-builder-config_v1_configmap.yaml must be customized to use a different builder base image, -// before building a workflow. -// The following ordered criteria are applied: -// 1) if the current platform has a configured platform.Spec.Build.Config.BaseImage, that base image must be used. -// 2) if the current sonataflow-operator-controllers-config.yaml has a configured SonataFlowBaseBuilderImageTag, that -// base image must be used. -// 3) No customization apply. -func GetCustomizedBuilderDockerfile(dockerfile string, platform operatorapi.SonataFlowPlatform) string { - if len(platform.Spec.Build.Config.BaseImage) > 0 { - dockerfile = strings.Replace(dockerfile, GetFromImageTagDockerfile(dockerfile), platform.Spec.Build.Config.BaseImage, 1) - } else if len(cfg.GetCfg().SonataFlowBaseBuilderImageTag) > 0 { - dockerfile = strings.Replace(dockerfile, GetFromImageTagDockerfile(dockerfile), cfg.GetCfg().SonataFlowBaseBuilderImageTag, 1) - } - return dockerfile -} - -func GetFromImageTagDockerfile(dockerfile string) string { - res := builderDockerfileFromRE.FindAllStringSubmatch(dockerfile, 1) - return strings.Trim(res[0][1], " ") -} - -// ReplaceFromImageTagDockerfile replaces the "FROM" clause from the given dockerfile with the given fromReplacement. -// For example: "FROM myimage:latest AS builder" -func ReplaceFromImageTagDockerfile(dockerfile string, fromReplacement string) string { - return string(builderDockerfileFromRE.ReplaceAll([]byte(dockerfile), []byte(fromReplacement))) -} - -func SafeUpdatePlatform(ctx context.Context, target *operatorapi.SonataFlowPlatform) error { - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - refreshedInst := &operatorapi.SonataFlowPlatform{} - if getErr := utils.GetClient().Get(ctx, types.NamespacedName{Namespace: target.Namespace, Name: target.Name}, refreshedInst); getErr != nil { - return getErr - } - refreshedInst.Spec = target.Spec - if updateErr := utils.GetClient().Update(ctx, refreshedInst); updateErr != nil { - return updateErr - } - return nil - }) -} - -func SafeUpdatePlatformStatus(ctx context.Context, target *operatorapi.SonataFlowPlatform) error { - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - refreshedInst := &operatorapi.SonataFlowPlatform{} - if getErr := utils.GetClient().Get(ctx, types.NamespacedName{Namespace: target.Namespace, Name: target.Name}, refreshedInst); getErr != nil { - return getErr - } - refreshedInst.Status = target.Status - if updateErr := utils.GetClient().Status().Update(ctx, refreshedInst); updateErr != nil { - return updateErr - } - return nil - }) -} diff --git a/internal/controller/platform/platformutils_test.go b/internal/controller/platform/platformutils_test.go deleted file mode 100644 index 03060d0c..00000000 --- a/internal/controller/platform/platformutils_test.go +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "fmt" - "os" - "regexp" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/test" -) - -const dockerFile = "FROM quay.io/kubesmarts/incubator-kie-sonataflow-builder:main AS builder\n\n# ETC, \n\n# ETC, \n\n# ETC" - -func TestSonataFlowBuildController(t *testing.T) { - platform := test.GetBasePlatform() - dockerfileBytes, err := os.ReadFile("testdata/platformTest.Dockerfile") - if err != nil { - assert.Fail(t, "Unable to read base Dockerfile") - } - dockerfile := string(dockerfileBytes) - - // Test 1: Verify that platform base image is used when set - platform.Spec.Build.Config.BaseImage = test.CommonImageTag - resDefault := GetCustomizedBuilderDockerfile(dockerfile, *platform) - foundDefault, err := regexp.MatchString(fmt.Sprintf("FROM %s AS builder", test.CommonImageTag), resDefault) - assert.NoError(t, err) - assert.True(t, foundDefault, "Expected platform base image to be used in Dockerfile") - - // Test 2: Verify override with different productized image - platform.Spec.Build.Config.BaseImage = "host2.org/namespace2/builder2:main" - resProductized := GetCustomizedBuilderDockerfile(dockerfile, *platform) - foundProductized, err := regexp.MatchString(fmt.Sprintf("FROM %s AS builder", platform.Spec.Build.Config.BaseImage), resProductized) - assert.NoError(t, err) - assert.True(t, foundProductized, "Expected override base image to be used in Dockerfile") -} - -func TestGetCustomizedBuilderDockerfile_NoBaseImageCustomization(t *testing.T) { - sfp := v1alpha08.SonataFlowPlatform{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{}, - Spec: v1alpha08.SonataFlowPlatformSpec{}, - Status: v1alpha08.SonataFlowPlatformStatus{}, - } - customizedDockerfile := GetCustomizedBuilderDockerfile(dockerFile, sfp) - assert.Equal(t, dockerFile, customizedDockerfile) -} - -func TestGetCustomizedBuilderDockerfile_BaseImageCustomizationFromPlatform(t *testing.T) { - sfp := v1alpha08.SonataFlowPlatform{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{}, - Spec: v1alpha08.SonataFlowPlatformSpec{ - Build: v1alpha08.BuildPlatformSpec{ - Template: v1alpha08.BuildTemplate{}, - Config: v1alpha08.BuildPlatformConfig{ - BaseImage: test.CommonImageTag, - }, - }, - }, - Status: v1alpha08.SonataFlowPlatformStatus{}, - } - - expectedDockerFile := fmt.Sprintf("FROM %s AS builder\n\n# ETC, \n\n# ETC, \n\n# ETC", test.CommonImageTag) - customizedDockerfile := GetCustomizedBuilderDockerfile(dockerFile, sfp) - assert.Equal(t, expectedDockerFile, customizedDockerfile) -} - -func TestGetCustomizedBuilderDockerfile_BaseImageCustomizationFromControllersConfig(t *testing.T) { - sfp := v1alpha08.SonataFlowPlatform{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{}, - Spec: v1alpha08.SonataFlowPlatformSpec{}, - Status: v1alpha08.SonataFlowPlatformStatus{}, - } - - _, err := cfg.InitializeControllersCfgAt("../cfg/testdata/controllers-cfg-test.yaml") - assert.NoError(t, err) - - expectedDockerFile := "FROM local/sonataflow-builder:1.0.0 AS builder\n\n# ETC, \n\n# ETC, \n\n# ETC" - customizedDockerfile := GetCustomizedBuilderDockerfile(dockerFile, sfp) - assert.Equal(t, expectedDockerFile, customizedDockerfile) -} diff --git a/internal/controller/platform/services/properties.go b/internal/controller/platform/services/properties.go deleted file mode 100644 index 4a8b76a5..00000000 --- a/internal/controller/platform/services/properties.go +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - "fmt" - "net/url" - "strings" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" - - "github.com/magiconair/properties" -) - -const DefaultHTTPServicePortInt = 8080 - -var ( - immutableApplicationProperties = fmt.Sprintf("quarkus.http.port=%d\n"+ - "quarkus.http.host=0.0.0.0\n"+ - "quarkus.devservices.enabled=false\n"+ - "quarkus.kogito.devservices.enabled=false\n", DefaultHTTPServicePortInt) - _ ServiceAppPropertyHandler = &serviceAppPropertyHandler{} -) - -type serviceAppPropertyHandler struct { - userProperties string - serviceHandler PlatformServiceHandler - defaultManagedProperties *properties.Properties -} - -type ServiceAppPropertyHandler interface { - WithUserProperties(userProperties string) ServiceAppPropertyHandler - Build() string -} - -// NewServiceAppPropertyHandler creates the default service configurations property handler -// The set of properties is initialized with the operator provided immutable properties. -// The set of defaultManagedProperties is initialized with the operator provided properties that the user might override. -func NewServiceAppPropertyHandler(serviceHandler PlatformServiceHandler) (ServiceAppPropertyHandler, error) { - handler := &serviceAppPropertyHandler{} - props, err := serviceHandler.GenerateServiceProperties() - if err != nil { - return nil, err - } - handler.defaultManagedProperties = props - return handler, nil -} - -func (a *serviceAppPropertyHandler) WithUserProperties(userProperties string) ServiceAppPropertyHandler { - a.userProperties = userProperties - return a -} - -func (a *serviceAppPropertyHandler) Build() string { - var props *properties.Properties - var propErr error = nil - if len(a.userProperties) == 0 { - props = properties.NewProperties() - } else { - props, propErr = properties.LoadString(a.userProperties) - } - if propErr != nil { - klog.V(log.D).InfoS("Can't load user's property", "service", a.serviceHandler.GetServiceName(), "properties", a.userProperties) - props = properties.NewProperties() - } - props = utils.NewApplicationPropertiesBuilder(). - WithInitialProperties(props). - WithImmutableProperties(properties.MustLoadString(immutableApplicationProperties)). - WithDefaultManagedProperties(a.defaultManagedProperties). - Build() - props.Sort() - return props.String() -} - -func generateReactiveURL(postgresSpec *operatorapi.PersistencePostgreSQL, schema string, namespace string, dbName string, port int) (string, error) { - if len(postgresSpec.JdbcUrl) > 0 { - s := strings.TrimLeft(postgresSpec.JdbcUrl, "jdbc:") - u, err := url.Parse(s) - if err != nil { - return "", err - } - ret := fmt.Sprintf("%s://", u.Scheme) - if len(u.User.Username()) > 0 { - p, ok := u.User.Password() - if ok { - ret = fmt.Sprintf("%s%s:%s@", ret, u.User.Username(), p) - } - } - ret = fmt.Sprintf("%s%s%s", ret, u.Host, u.Path) - kv, err := url.ParseQuery(u.RawQuery) - if err != nil { - return "", err - } - var spv string - if v, ok := kv["search_path"]; ok { - for _, val := range v { - if len(val) != 0 { - spv = v[0] - } - } - } else if v, ok := kv["currentSchema"]; ok { - for _, val := range v { - if len(val) != 0 { - spv = v[0] - } - } - } - if len(spv) > 0 { - return fmt.Sprintf("%s?search_path=%s", ret, spv), nil - } - return ret, nil - } - databaseSchema := schema - if len(postgresSpec.ServiceRef.DatabaseSchema) > 0 { - databaseSchema = postgresSpec.ServiceRef.DatabaseSchema - } - databaseNamespace := namespace - if len(postgresSpec.ServiceRef.Namespace) > 0 { - databaseNamespace = postgresSpec.ServiceRef.Namespace - } - dataSourcePort := port - if postgresSpec.ServiceRef.Port != nil { - dataSourcePort = *postgresSpec.ServiceRef.Port - } - databaseName := dbName - if len(postgresSpec.ServiceRef.DatabaseName) > 0 { - databaseName = postgresSpec.ServiceRef.DatabaseName - } - return fmt.Sprintf("%s://%s:%d/%s?search_path=%s", constants.PersistenceTypePostgreSQL, postgresSpec.ServiceRef.Name+"."+databaseNamespace, dataSourcePort, databaseName, databaseSchema), nil -} - -// GenerateDataIndexWorkflowProperties returns the set of application properties required for the workflow to interact -// with the Data Index. For the calculation this function considers if the Data Index is present in the -// SonataFlowPlatform, if not present, no properties. -// Never nil. -func GenerateDataIndexWorkflowProperties(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (*properties.Properties, error) { - props := properties.NewProperties() - props.Set(constants.KogitoProcessDefinitionsEventsEnabled, "false") - props.Set(constants.KogitoProcessInstancesEventsEnabled, "false") - sink, err := knative.GetWorkflowSink(workflow, platform) - if err != nil { - return nil, err - } - di := NewDataIndexHandler(platform) - if !profiles.IsDevProfile(workflow) && workflow != nil && workflow.Status.Services != nil && workflow.Status.Services.DataIndexRef != nil { - serviceBaseUrl := workflow.Status.Services.DataIndexRef.Url - if di.IsServiceEnabled() && len(serviceBaseUrl) > 0 { - props.Set(constants.KogitoProcessDefinitionsEventsEnabled, "true") - props.Set(constants.KogitoProcessInstancesEventsEnabled, "true") - props.Set(constants.KogitoProcessDefinitionsEventsErrorsEnabled, "true") - if sink != nil { - props.Set(constants.KogitoProcessDefinitionsEventsConnector, constants.QuarkusHTTP) - props.Set(constants.KogitoProcessInstancesEventsConnector, constants.QuarkusHTTP) - props.Set(constants.KogitoProcessDefinitionsEventsURL, constants.KnativeInjectedEnvVar) - props.Set(constants.KogitoProcessInstancesEventsURL, constants.KnativeInjectedEnvVar) - props.Set(constants.KogitoProcessDefinitionsEventsMethod, constants.Post) - props.Set(constants.KogitoProcessInstancesEventsMethod, constants.Post) - } else { - props.Set(constants.KogitoDataIndexHealthCheckEnabled, "true") - props.Set(constants.KogitoDataIndexURL, serviceBaseUrl) - props.Set(constants.KogitoProcessDefinitionsEventsURL, serviceBaseUrl+constants.KogitoProcessDefinitionsEventsPath) - props.Set(constants.KogitoProcessInstancesEventsURL, serviceBaseUrl+constants.KogitoProcessInstancesEventsPath) - } - } - } - props.Sort() - - return props, nil -} - -// GenerateJobServiceWorkflowProperties returns the set of application properties required for the workflow to interact -// with the Job Service. For the calculation this function considers if the Job Service is present in the -// SonataFlowPlatform, if not present, no properties. -// Never nil. -func GenerateJobServiceWorkflowProperties(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (*properties.Properties, error) { - props := properties.NewProperties() - props.Set(constants.JobServiceRequestEventsConnector, constants.QuarkusHTTP) - props.Set(constants.JobServiceRequestEventsURL, fmt.Sprintf("%s://localhost%s", constants.DefaultHTTPProtocol, constants.JobServiceJobEventsPath)) - sink, err := knative.GetWorkflowSink(workflow, platform) - if err != nil { - return nil, err - } - js := NewJobServiceHandler(platform) - if !profiles.IsDevProfile(workflow) && workflow != nil && workflow.Status.Services != nil && workflow.Status.Services.JobServiceRef != nil { - serviceBaseUrl := workflow.Status.Services.JobServiceRef.Url - if js.IsServiceEnabled() && len(serviceBaseUrl) > 0 { - if sink != nil { - props.Set(constants.JobServiceRequestEventsURL, constants.KnativeInjectedEnvVar) - props.Set(constants.JobServiceRequestEventsConnector, constants.QuarkusHTTP) - props.Set(constants.JobServiceRequestEventsMethod, constants.Post) - } else { - if workflowdef.HasTimeouts(workflow) { - props.Set(constants.KogitoJobServiceHealthCheckEnabled, "true") - } - props.Set(constants.KogitoJobServiceURL, serviceBaseUrl) - props.Set(constants.JobServiceRequestEventsURL, serviceBaseUrl+constants.JobServiceJobEventsPath) - } - } - } - props.Sort() - - return props, nil -} diff --git a/internal/controller/platform/services/properties_services_test.go b/internal/controller/platform/services/properties_services_test.go deleted file mode 100644 index 529dfe33..00000000 --- a/internal/controller/platform/services/properties_services_test.go +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "github.com/magiconair/properties" -) - -var ( - enabled = true - disabled = false -) - -var _ = Describe("PlatformServiceHandler properties", func() { - - var _ = Context("for service properties", func() { - - var _ = Context("defining the application properties generated for the deployment of the", func() { - - DescribeTable("Job Service", - func(plfm *operatorapi.SonataFlowPlatform, expectedProperties *properties.Properties) { - js := NewJobServiceHandler(plfm) - handler, err := NewServiceAppPropertyHandler(js) - Expect(err).NotTo(HaveOccurred()) - p, err := properties.LoadString(handler.Build()) - Expect(err).NotTo(HaveOccurred()) - p.Sort() - Expect(p).To(Equal(expectedProperties)) - }, - Entry("with an empty spec", generatePlatform(emptyJobServiceSpec(), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceDeploymentDevProperties()), - Entry("with enabled field undefined and with ephemeral persistence", - generatePlatform(setJobServiceEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceDeploymentDevProperties()), - Entry("with enabled field undefined and with postgreSQL persistence", - generatePlatform(setJobServiceEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateJobServiceDeploymentWithPostgreSQLProperties()), - Entry("with enabled field set to false and with ephemeral persistence", - generatePlatform(setJobServiceEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceDeploymentDevProperties()), - Entry("with enabled field set to false and with postgreSQL persistence", - generatePlatform(setJobServiceEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateJobServiceDeploymentWithPostgreSQLProperties()), - Entry("with enabled field set to true and with ephemeral persistence", - generatePlatform(setJobServiceEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceDeploymentDevProperties()), - Entry("with enabled field set to true and with postgreSQL persistence", - generatePlatform(setJobServiceEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateJobServiceDeploymentWithPostgreSQLProperties()), - Entry("with both services with enabled field set to true and with ephemeral persistence", - generatePlatform(setJobServiceEnabledValue(&enabled), setDataIndexEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceDeploymentWithDataIndexAndEphemeralProperties()), - Entry("with both services with enabled field set to true and postgreSQL persistence for both", - generatePlatform(setJobServiceEnabledValue(&enabled), setDataIndexEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema"), setDataIndexJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateJobServiceDeploymentWithDataIndexAndPostgreSQLProperties()), - ) - - DescribeTable("Data Index", func(plfm *operatorapi.SonataFlowPlatform, expectedProperties *properties.Properties) { - di := NewDataIndexHandler(plfm) - handler, err := NewServiceAppPropertyHandler(di) - Expect(err).NotTo(HaveOccurred()) - p, err := properties.LoadString(handler.Build()) - Expect(err).NotTo(HaveOccurred()) - p.Sort() - Expect(p).To(Equal(expectedProperties)) - }, - Entry("with ephemeral persistence", generatePlatform(emptyDataIndexServiceSpec(), setPlatformName("foo"), setPlatformNamespace("default")), generateDataIndexDeploymentProperties()), - Entry("with postgreSQL persistence", generatePlatform(emptyDataIndexServiceSpec(), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexDeploymentProperties()), - ) - }) - - }) - -}) - -func generateJobServiceDeploymentDevProperties() *properties.Properties { - p := properties.NewProperties() - p.Set("kogito.service.url", "http://foo-jobs-service.default") - p.Set("quarkus.devservices.enabled", "false") - p.Set("quarkus.http.host", "0.0.0.0") - p.Set("quarkus.http.port", "8080") - p.Set("quarkus.kogito.devservices.enabled", "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.management.JobServiceLeaderLivenessHealthCheck".enabled`, "true") - p.Set("kogito.jobs-service.management.leader-check.expiration-in-seconds", "60") - p.Sort() - return p -} - -func generateDataIndexDeploymentProperties() *properties.Properties { - p := properties.NewProperties() - p.Set("kogito.service.url", "http://foo-data-index-service.default") - p.Set("quarkus.devservices.enabled", "false") - p.Set("quarkus.http.host", "0.0.0.0") - p.Set("quarkus.http.port", "8080") - p.Set("quarkus.kogito.devservices.enabled", "false") - p.Set("quarkus.smallrye-health.check.\"io.quarkus.kafka.client.health.KafkaHealthCheck\".enabled", "false") - p.Sort() - return p -} - -func generateJobServiceDeploymentWithPostgreSQLProperties() *properties.Properties { - p := properties.NewProperties() - p.Set("kogito.service.url", "http://foo-jobs-service.default") - p.Set("quarkus.devservices.enabled", "false") - p.Set("quarkus.http.host", "0.0.0.0") - p.Set("quarkus.http.port", "8080") - p.Set("quarkus.kogito.devservices.enabled", "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.management.JobServiceLeaderLivenessHealthCheck".enabled`, "true") - p.Set("kogito.jobs-service.management.leader-check.expiration-in-seconds", "60") - p.Sort() - return p -} - -func generateJobServiceDeploymentWithDataIndexAndEphemeralProperties() *properties.Properties { - p := properties.NewProperties() - p.Set("kogito.service.url", "http://foo-jobs-service.default") - p.Set("kogito.jobs-service.http.job-status-change-events", "true") - p.Set("mp.messaging.outgoing.kogito-job-service-job-status-events-http.url", "http://foo-data-index-service.default/jobs") - p.Set("quarkus.devservices.enabled", "false") - p.Set("quarkus.http.host", "0.0.0.0") - p.Set("quarkus.http.port", "8080") - p.Set("quarkus.kogito.devservices.enabled", "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.management.JobServiceLeaderLivenessHealthCheck".enabled`, "true") - p.Set("kogito.jobs-service.management.leader-check.expiration-in-seconds", "60") - p.Sort() - return p -} - -func generateJobServiceDeploymentWithDataIndexAndPostgreSQLProperties() *properties.Properties { - p := properties.NewProperties() - p.Set("kogito.service.url", "http://foo-jobs-service.default") - p.Set("kogito.jobs-service.http.job-status-change-events", "true") - p.Set("mp.messaging.outgoing.kogito-job-service-job-status-events-http.url", "http://foo-data-index-service.default/jobs") - p.Set("quarkus.devservices.enabled", "false") - p.Set("quarkus.http.host", "0.0.0.0") - p.Set("quarkus.http.port", "8080") - p.Set("quarkus.kogito.devservices.enabled", "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled`, "false") - p.Set(`quarkus.smallrye-health.check."org.kie.kogito.jobs.service.management.JobServiceLeaderLivenessHealthCheck".enabled`, "true") - p.Set("kogito.jobs-service.management.leader-check.expiration-in-seconds", "60") - p.Sort() - return p -} - -type plfmOptionFn func(p *operatorapi.SonataFlowPlatform) - -func generatePlatform(opts ...plfmOptionFn) *operatorapi.SonataFlowPlatform { - plfm := &operatorapi.SonataFlowPlatform{} - for _, f := range opts { - f(plfm) - } - return plfm -} - -func setJobServiceEnabledValue(v *bool) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.JobService == nil { - p.Spec.Services.JobService = &operatorapi.JobServiceServiceSpec{} - } - p.Spec.Services.JobService.Enabled = v - } -} - -func setDataIndexEnabledValue(v *bool) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.DataIndex == nil { - p.Spec.Services.DataIndex = &operatorapi.DataIndexServiceSpec{} - } - p.Spec.Services.DataIndex.Enabled = v - } -} - -func emptyDataIndexServiceSpec() plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.DataIndex == nil { - p.Spec.Services.DataIndex = &operatorapi.DataIndexServiceSpec{} - } - } -} - -func emptyJobServiceSpec() plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.JobService == nil { - p.Spec.Services.JobService = &operatorapi.JobServiceServiceSpec{} - } - } -} - -func setPlatformNamespace(namespace string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - p.Namespace = namespace - } -} - -func setPlatformName(name string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - p.Name = name - } -} - -func setJobServiceJDBC(jdbc string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.JobService == nil { - p.Spec.Services.JobService = &operatorapi.JobServiceServiceSpec{} - } - if p.Spec.Services.JobService.Persistence == nil { - p.Spec.Services.JobService.Persistence = &operatorapi.PersistenceOptionsSpec{} - } - if p.Spec.Services.JobService.Persistence.PostgreSQL == nil { - p.Spec.Services.JobService.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} - } - p.Spec.Services.JobService.Persistence.PostgreSQL.JdbcUrl = jdbc - } -} - -func setDataIndexJDBC(jdbc string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.DataIndex == nil { - p.Spec.Services.DataIndex = &operatorapi.DataIndexServiceSpec{} - } - if p.Spec.Services.DataIndex.Persistence == nil { - p.Spec.Services.DataIndex.Persistence = &operatorapi.PersistenceOptionsSpec{} - } - if p.Spec.Services.DataIndex.Persistence.PostgreSQL == nil { - p.Spec.Services.DataIndex.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} - } - p.Spec.Services.DataIndex.Persistence.PostgreSQL.JdbcUrl = jdbc - } -} diff --git a/internal/controller/platform/services/properties_test.go b/internal/controller/platform/services/properties_test.go deleted file mode 100644 index 3c288e19..00000000 --- a/internal/controller/platform/services/properties_test.go +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" -) - -const ( - defaultSchema = "schema" -) - -var _ = Describe("Platform properties", func() { - - var _ = Context("PostgreSQL properties", func() { - var _ = DescribeTable("Generate a reactive URL", func(spec *operatorapi.PersistencePostgreSQL, expectedReactiveURL string, expectedError bool) { - res, err := generateReactiveURL(spec, defaultSchema, "default", constants.DefaultDatabaseName, constants.DefaultPostgreSQLPort) - if expectedError { - Expect(err).NotTo(BeNil()) - } else { - Expect(res).To(BeIdenticalTo(expectedReactiveURL)) - } - }, - Entry("With an invalid URL", generatePostgreSQLOptions(setJDBC("jdbc:\\postgress://url to fail/fail?here&and&here")), "", true), - Entry("Empty JDBC string in spec", generatePostgreSQLOptions(setServiceName("svcName")), "postgresql://svcName.default:5432/sonataflow?search_path=schema", false), - Entry("JDBC in spec with duplicated jdbc prefix and no currentSchema in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:jdbc:postgres://host.com:5432/path?k=v#f")), "postgres://host.com:5432/path", false), - Entry("JDBC in spec with username and password and no currentSchema in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgres://user:pass@host.com:5432/dbName?k=v#f")), "postgres://user:pass@host.com:5432/dbName", false), - Entry("JDBC in spec without currentSchema in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:5432/sonataflow")), "postgresql://postgres:5432/sonataflow", false), - Entry("JDBC in spec with duplicated currentSchema in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema¤tSchema=myschema2")), "postgresql://postgres:5432/sonataflow?search_path=myschema", false), - Entry("JDBC in spec with currentSchema first and search_path later in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema&search_path=myschema2")), "postgresql://postgres:5432/sonataflow?search_path=myschema2", false), - Entry("JDBC in spec with search_path first and currentSchema later in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema&search_path=myschema2")), "postgresql://postgres:5432/sonataflow?search_path=myschema2", false), - Entry("JDBC in spec with empty value in currentSchema parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:342/sonataflow?currentSchema")), "postgresql://postgres:342/sonataflow", false), - Entry("JDBC in spec with currentSchema in URL parameter", - generatePostgreSQLOptions(setJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), "postgresql://postgres:5432/sonataflow?search_path=myschema", false), - Entry("With only database service namespace defined", - generatePostgreSQLOptions(setServiceName("svc"), setServiceNamespace("test")), "postgresql://svc.test:5432/sonataflow?search_path=schema", false), - Entry("With only database schema defined", - generatePostgreSQLOptions(setServiceName("svc"), setDatabaseSchemaName("myschema")), "postgresql://svc.default:5432/sonataflow?search_path=myschema", false), - Entry("With only database port defined", - generatePostgreSQLOptions(setServiceName("svc"), setDBPort(3432)), "postgresql://svc.default:3432/sonataflow?search_path=schema", false), - Entry("With only database name defined", - generatePostgreSQLOptions(setServiceName("svc"), setDatabaseName("foo")), "postgresql://svc.default:5432/foo?search_path=schema", false), - ) - }) -}) - -type optionFn func(*operatorapi.PersistencePostgreSQL) - -func generatePostgreSQLOptions(options ...optionFn) *operatorapi.PersistencePostgreSQL { - p := &operatorapi.PersistencePostgreSQL{} - for _, f := range options { - f(p) - } - return p -} - -func setJDBC(url string) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - o.JdbcUrl = url - } -} - -func setServiceName(svcName string) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - if o.ServiceRef == nil { - o.ServiceRef = &operatorapi.PostgreSQLServiceOptions{} - } - if o.ServiceRef.SQLServiceOptions == nil { - o.ServiceRef.SQLServiceOptions = &operatorapi.SQLServiceOptions{} - } - o.ServiceRef.Name = svcName - } -} - -func setDatabaseSchemaName(dbSchemaName string) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - if o.ServiceRef == nil { - o.ServiceRef = &operatorapi.PostgreSQLServiceOptions{} - } - o.ServiceRef.DatabaseSchema = dbSchemaName - } -} - -func setDatabaseName(dbName string) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - if o.ServiceRef == nil { - o.ServiceRef = &operatorapi.PostgreSQLServiceOptions{} - } - if o.ServiceRef.SQLServiceOptions == nil { - o.ServiceRef.SQLServiceOptions = &operatorapi.SQLServiceOptions{} - } - o.ServiceRef.DatabaseName = dbName - } -} - -func setServiceNamespace(svcNamespace string) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - if o.ServiceRef == nil { - o.ServiceRef = &operatorapi.PostgreSQLServiceOptions{} - } - if o.ServiceRef.SQLServiceOptions == nil { - o.ServiceRef.SQLServiceOptions = &operatorapi.SQLServiceOptions{} - } - o.ServiceRef.Namespace = svcNamespace - } -} - -func setDBPort(portNumber int) optionFn { - return func(o *operatorapi.PersistencePostgreSQL) { - if o.ServiceRef == nil { - o.ServiceRef = &operatorapi.PostgreSQLServiceOptions{} - } - if o.ServiceRef.SQLServiceOptions == nil { - o.ServiceRef.SQLServiceOptions = &operatorapi.SQLServiceOptions{} - } - o.ServiceRef.Port = &portNumber - } -} diff --git a/internal/controller/platform/services/secrets.go b/internal/controller/platform/services/secrets.go deleted file mode 100644 index caf2c1a8..00000000 --- a/internal/controller/platform/services/secrets.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" -) - -func GetSecretKeyValueString(ctx context.Context, secretName string, secretKey string, nameSpace string) (string, error) { - secret := corev1.Secret{} - err := utils.GetClient().Get(ctx, ctrl.ObjectKey{Namespace: nameSpace, Name: secretName}, &secret) - - if err != nil { - klog.V(log.E).InfoS("Error extracting secret: ", "namespace", nameSpace, "error", err) - return "", err - } - - return string(secret.Data[secretKey]), nil -} diff --git a/internal/controller/platform/services/services.go b/internal/controller/platform/services/services.go deleted file mode 100644 index 9cf342d8..00000000 --- a/internal/controller/platform/services/services.go +++ /dev/null @@ -1,883 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - "fmt" - "strconv" - - "github.com/kubesmarts/logic-operator/api/version" - - appsv1 "k8s.io/api/apps/v1" - - "github.com/imdario/mergo" - "github.com/magiconair/properties" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" - "knative.dev/pkg/kmeta" - "knative.dev/pkg/tracker" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/utils/kubernetes" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" -) - -const ( - quarkusFlywayMigrateAtStart = "QUARKUS_FLYWAY_MIGRATE_AT_START" - kogitoJobsServiceLoadJobsErrorStrategy = "KOGITO_JOBS_SERVICE_LOADJOBERRORSTRATEGY" - WaitingKnativeEventing = "WaitingKnativeEventing" -) - -type PlatformServiceHandler interface { - // GetContainerName returns the name of the service's container in the deployment. - GetContainerName() string - // GetServiceImageName returns the image name of the service's container. It takes in the service and persistence types and returns a string - // that contains the FQDN of the image, including the tag. - GetServiceImageName(persistenceName constants.PersistenceType) string - // GetServiceName returns the name of the kubernetes service prefixed with the platform name - GetServiceName() string - // GetServiceCmName returns the name of the configmap associated to the service - GetServiceCmName() string - // GetEnvironmentVariables returns the env variables to be injected to the service container - GetEnvironmentVariables() []corev1.EnvVar - // GetPodResourceRequirements returns the pod's memory and CPU resource requirements - // Values for job service taken from - // https://github.com/parodos-dev/orchestrator-helm-chart/blob/52d09eda56fdbed3060782df29847c97f172600f/charts/orchestrator/values.yaml#L68-L72 - GetPodResourceRequirements() corev1.ResourceRequirements - // GetReplicaCount Returns the default pod replica count for the given service - GetReplicaCount() int32 - // GetDeploymentStrategy Returns the deployment strategy for the service - GetDeploymentStrategy() appsv1.DeploymentStrategy - - // MergeContainerSpec performs a merge with override using the containerSpec argument and the expected values based on the service's pod template specifications. The returning - // object is the merged result - MergeContainerSpec(containerSpec *corev1.Container) (*corev1.Container, error) - - // ConfigurePersistence sets the persistence's image and environment values when it is defined in the Persistence field of the service, overriding any existing value. - ConfigurePersistence(containerSpec *corev1.Container) *corev1.Container - - // MergePodSpec performs a merge with override between the podSpec argument and the expected values based on the service's pod template specification. The returning - // object is the result of the merge - MergePodSpec(podSpec corev1.PodSpec) (corev1.PodSpec, error) - // GenerateServiceProperties returns a property object that contains the application properties required by the service deployment - GenerateServiceProperties() (*properties.Properties, error) - // GenerateKnativeResources returns knative resources that bridge between workflow deploys and the service - GenerateKnativeResources(platform *operatorapi.SonataFlowPlatform, lbl map[string]string) ([]client.Object, *corev1.Event, error) - - // IsServiceSetInSpec returns true if the service is set in the spec. - IsServiceSetInSpec() bool - // IsServiceEnabledInSpec returns true if the service is enabled in the spec. - IsServiceEnabledInSpec() bool - // IsPersistenceEnabledtInSpec returns true if the service has persistence set in the spec. - IsPersistenceEnabledtInSpec() bool - // GetLocalServiceBaseUrl returns the base url of the local service - GetLocalServiceBaseUrl() string - // GetServiceBaseUrl returns the base url of the service, based on whether using local or cluster-scoped service. - GetServiceBaseUrl() string - // IsServiceEnabled returns true if the service is enabled in either the spec or the status.clusterPlatformRef. - IsServiceEnabled() bool - // SetServiceUrlInPlatformStatus sets the service url in the platform's status. if reconciled instance does not have service set in spec AND - // if cluster referenced platform has said service enabled, use the cluster platform's service - SetServiceUrlInPlatformStatus(clusterRefPlatform *operatorapi.SonataFlowPlatform) - // SetServiceUrlInWorkflowStatus sets the service url in a workflow's status. - SetServiceUrlInWorkflowStatus(workflow *operatorapi.SonataFlow) - - // GetServiceSource returns the source Broker configured for the given service by applying the following precedence rule. - // The source declared in the given service definition is returned first, if any, otherwise a source declared in the - // service platform is returned, if any. - GetServiceSource() *duckv1.Destination - - // Check if K_SINK has injected for Job Service. No Op for Data Index - CheckKSinkInjected() (bool, error) - - // Returns whether job based, service based or no DB migration is needed - GetDBMigrationStrategy() operatorapi.DBMigrationStrategyType - - // AcceptsHPA returns true if the service accepts an external HPA configuration. - AcceptsHPA() bool - - // AcceptsPDB returns true if the service accepts the operator managed PDB generation. - AcceptsPDB() bool - - // GetPDBSpec returns the configured PodDisruptionBudgetSpec for the given service. - GetPDBSpec() *operatorapi.PodDisruptionBudgetSpec -} - -type DataIndexHandler struct { - platform *operatorapi.SonataFlowPlatform -} - -func (d *DataIndexHandler) AcceptsHPA() bool { - return true -} - -func (d *DataIndexHandler) AcceptsPDB() bool { - return true -} - -func (d *DataIndexHandler) GetPDBSpec() *operatorapi.PodDisruptionBudgetSpec { - return d.platform.Spec.Services.DataIndex.ServiceSpec.PodTemplate.PodDisruptionBudget -} - -// GetDBMigrationStrategy returns DB migration approach -func (d *DataIndexHandler) GetDBMigrationStrategy() operatorapi.DBMigrationStrategyType { - return GetDBMigrationStrategy(d.platform.Spec.Services.DataIndex.Persistence) -} - -func NewDataIndexHandler(platform *operatorapi.SonataFlowPlatform) PlatformServiceHandler { - return &DataIndexHandler{platform: platform} -} - -func (d *DataIndexHandler) GetContainerName() string { - return constants.DataIndexServiceName -} - -func (d DataIndexHandler) GetServiceImageName(persistenceType constants.PersistenceType) string { - if persistenceType == constants.PersistenceTypePostgreSQL && len(cfg.GetCfg().DataIndexPostgreSQLImageTag) > 0 { - return cfg.GetCfg().DataIndexPostgreSQLImageTag - } - if persistenceType == constants.PersistenceTypeEphemeral && len(cfg.GetCfg().DataIndexEphemeralImageTag) > 0 { - return cfg.GetCfg().DataIndexEphemeralImageTag - } - // returns "docker.io/apache/incubator-kie-kogito-data-index-:" - return fmt.Sprintf("%s-%s-%s:%s", constants.ImageNamePrefix, constants.DataIndexName, persistenceType.String(), version.GetImageTagVersion()) -} - -func (d *DataIndexHandler) GetServiceName() string { - return fmt.Sprintf("%s-%s", d.platform.Name, constants.DataIndexServiceName) -} - -func (d DataIndexHandler) SetServiceUrlInPlatformStatus(clusterRefPlatform *operatorapi.SonataFlowPlatform) { - psDI := NewDataIndexHandler(clusterRefPlatform) - if !isServicesSet(d.platform) && psDI.IsServiceEnabledInSpec() { - if d.platform.Status.ClusterPlatformRef != nil { - if d.platform.Status.ClusterPlatformRef.Services == nil { - d.platform.Status.ClusterPlatformRef.Services = &operatorapi.PlatformServicesStatus{} - } - d.platform.Status.ClusterPlatformRef.Services.DataIndexRef = &operatorapi.PlatformServiceRefStatus{ - Url: psDI.GetLocalServiceBaseUrl(), - } - } - } -} - -func (d DataIndexHandler) SetServiceUrlInWorkflowStatus(workflow *operatorapi.SonataFlow) { - if !profiles.IsDevProfile(workflow) && d.IsServiceEnabled() { - if workflow.Status.Services == nil { - workflow.Status.Services = &operatorapi.PlatformServicesStatus{} - } - workflow.Status.Services.DataIndexRef = &operatorapi.PlatformServiceRefStatus{ - Url: d.GetServiceBaseUrl(), - } - } -} - -func (d DataIndexHandler) IsServiceSetInSpec() bool { - return isDataIndexSet(d.platform) -} - -func (d *DataIndexHandler) IsServiceEnabledInSpec() bool { - return isDataIndexEnabled(d.platform) -} - -func (d DataIndexHandler) IsPersistenceEnabledtInSpec() bool { - return d.IsServiceSetInSpec() && d.platform.Spec.Services.DataIndex.Persistence != nil -} - -func (d *DataIndexHandler) isServiceEnabledInStatus() bool { - return d.platform != nil && d.platform.Status.ClusterPlatformRef != nil && - d.platform.Status.ClusterPlatformRef.Services != nil && d.platform.Status.ClusterPlatformRef.Services.DataIndexRef != nil && - !isServicesSet(d.platform) -} - -func (d *DataIndexHandler) IsServiceEnabled() bool { - return d.IsServiceEnabledInSpec() || d.isServiceEnabledInStatus() -} - -func (d *DataIndexHandler) GetServiceBaseUrl() string { - if d.IsServiceEnabledInSpec() { - return d.GetLocalServiceBaseUrl() - } - if d.isServiceEnabledInStatus() { - return d.platform.Status.ClusterPlatformRef.Services.DataIndexRef.Url - } - return "" -} - -func (d *DataIndexHandler) GetLocalServiceBaseUrl() string { - return GenerateServiceURL(constants.DefaultHTTPProtocol, d.platform.Namespace, d.GetServiceName()) -} - -func (d *DataIndexHandler) GetEnvironmentVariables() []corev1.EnvVar { - return []corev1.EnvVar{ - { - Name: "KOGITO_DATA_INDEX_QUARKUS_PROFILE", - Value: "http-events-support", - }, - } -} - -func (d *DataIndexHandler) GetPodResourceRequirements() corev1.ResourceRequirements { - return corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("1Gi"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("200m"), - corev1.ResourceMemory: resource.MustParse("1Gi"), - }, - } -} - -func (d *DataIndexHandler) MergePodSpec(podSpec corev1.PodSpec) (corev1.PodSpec, error) { - c := podSpec.DeepCopy() - err := mergo.Merge(c, d.platform.Spec.Services.DataIndex.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride) - return *c, err -} - -// hasPostgreSQLConfigured returns true when either the SonataFlow Platform PostgreSQL CR's structure or the one in the Data Index service specification is not nil -func (d *DataIndexHandler) hasPostgreSQLConfigured() bool { - return d.IsServiceSetInSpec() && - ((d.platform.Spec.Services.DataIndex.Persistence != nil && d.platform.Spec.Services.DataIndex.Persistence.PostgreSQL != nil) || - (d.platform.Spec.Persistence != nil && d.platform.Spec.Persistence.PostgreSQL != nil)) -} - -func GetDBMigrationStrategy(persistence *operatorapi.PersistenceOptionsSpec) operatorapi.DBMigrationStrategyType { - dbMigrationStrategy := operatorapi.DBMigrationStrategyNone - - if persistence != nil { - return operatorapi.DBMigrationStrategyType(persistence.DBMigrationStrategy) - } - - return dbMigrationStrategy -} - -func IsServiceBasedDBMigration(persistence *operatorapi.PersistenceOptionsSpec) bool { - dbMigrationStrategy := GetDBMigrationStrategy(persistence) - return dbMigrationStrategy == operatorapi.DBMigrationStrategyService -} - -func IsJobsBasedDBMigration(persistence *operatorapi.PersistenceOptionsSpec) bool { - dbMigrationStrategy := GetDBMigrationStrategy(persistence) - return dbMigrationStrategy == operatorapi.DBMigrationStrategyJob -} - -func IsNoDBMigration(persistence *operatorapi.PersistenceOptionsSpec) bool { - dbMigrationStrategy := GetDBMigrationStrategy(persistence) - return dbMigrationStrategy == operatorapi.DBMigrationStrategyNone || dbMigrationStrategy == "" -} - -func isDBMigrationStrategyService(persistence *v1alpha08.PersistenceOptionsSpec) string { - dbMigrationStrategyService := "true" - if persistence != nil { - dbMigrationStrategyService = strconv.FormatBool(IsServiceBasedDBMigration(persistence)) - } - - return dbMigrationStrategyService -} - -func (d *DataIndexHandler) ConfigurePersistence(containerSpec *corev1.Container) *corev1.Container { - if d.hasPostgreSQLConfigured() { - p := persistence.RetrievePostgreSQLConfiguration(d.platform.Spec.Services.DataIndex.Persistence, d.platform.Spec.Persistence, d.GetServiceName()) - c := containerSpec.DeepCopy() - c.Image = d.GetServiceImageName(constants.PersistenceTypePostgreSQL) - c.Env = append(c.Env, persistence.ConfigurePostgreSQLEnv(p.PostgreSQL, d.GetServiceName(), d.platform.Namespace, false)...) - - dbMigrationStrategyService := isDBMigrationStrategyService(d.platform.Spec.Services.DataIndex.Persistence) - - // specific to DataIndex - c.Env = append(c.Env, corev1.EnvVar{Name: quarkusFlywayMigrateAtStart, Value: dbMigrationStrategyService}) - return c - } - return containerSpec -} - -func (d DataIndexHandler) MergeContainerSpec(containerSpec *corev1.Container) (*corev1.Container, error) { - return mergeContainerSpec(containerSpec, &d.platform.Spec.Services.DataIndex.PodTemplate.Container) -} - -func (d *DataIndexHandler) GetReplicaCount() int32 { - if d.platform.Spec.Services.DataIndex.PodTemplate.Replicas != nil { - return *d.platform.Spec.Services.DataIndex.PodTemplate.Replicas - } - return 1 -} - -func (d *DataIndexHandler) GetDeploymentStrategy() appsv1.DeploymentStrategy { - return appsv1.DeploymentStrategy{} -} - -func (d *DataIndexHandler) GetServiceCmName() string { - return fmt.Sprintf("%s-props", d.GetServiceName()) -} - -func (d *DataIndexHandler) GetServiceSource() *duckv1.Destination { - if d.platform.Spec.Services.DataIndex.Source != nil { - return d.platform.Spec.Services.DataIndex.Source - } - return GetPlatformBroker(d.platform) -} - -func (d *DataIndexHandler) GenerateServiceProperties() (*properties.Properties, error) { - props := properties.NewProperties() - props.Set(constants.KogitoServiceURLProperty, d.GetLocalServiceBaseUrl()) - props.Set(constants.DataIndexKafkaHealthCheck, "false") - return props, nil -} - -func (d *DataIndexHandler) CheckKSinkInjected() (bool, error) { - return true, nil // No op -} - -type JobServiceHandler struct { - platform *operatorapi.SonataFlowPlatform -} - -func (d *JobServiceHandler) AcceptsHPA() bool { - return false -} - -func (d *JobServiceHandler) AcceptsPDB() bool { - return false -} - -func (d *JobServiceHandler) GetPDBSpec() *operatorapi.PodDisruptionBudgetSpec { - return nil -} - -// GetDBMigrationStrategy returns db migration approach otherwise -func (j *JobServiceHandler) GetDBMigrationStrategy() operatorapi.DBMigrationStrategyType { - return GetDBMigrationStrategy(j.platform.Spec.Services.JobService.Persistence) -} - -func NewJobServiceHandler(platform *operatorapi.SonataFlowPlatform) PlatformServiceHandler { - return &JobServiceHandler{platform: platform} -} - -func (j *JobServiceHandler) GetContainerName() string { - return constants.JobServiceName -} - -func (j JobServiceHandler) GetServiceImageName(persistenceType constants.PersistenceType) string { - if persistenceType == constants.PersistenceTypePostgreSQL && len(cfg.GetCfg().JobsServicePostgreSQLImageTag) > 0 { - return cfg.GetCfg().JobsServicePostgreSQLImageTag - } - if persistenceType == constants.PersistenceTypeEphemeral && len(cfg.GetCfg().JobsServiceEphemeralImageTag) > 0 { - return cfg.GetCfg().JobsServiceEphemeralImageTag - } - // returns "docker.io/apache/incubator-kie-kogito-jobs-service-:" - return fmt.Sprintf("%s-%s-%s:%s", constants.ImageNamePrefix, constants.JobServiceName, persistenceType.String(), version.GetImageTagVersion()) -} - -func (j *JobServiceHandler) GetServiceName() string { - return fmt.Sprintf("%s-%s", j.platform.Name, constants.JobServiceName) -} - -func (j *JobServiceHandler) GetServiceCmName() string { - return fmt.Sprintf("%s-props", j.GetServiceName()) -} - -func (j JobServiceHandler) SetServiceUrlInPlatformStatus(clusterRefPlatform *operatorapi.SonataFlowPlatform) { - psJS := NewJobServiceHandler(clusterRefPlatform) - if !isServicesSet(j.platform) && psJS.IsServiceEnabledInSpec() { - if j.platform.Status.ClusterPlatformRef != nil { - if j.platform.Status.ClusterPlatformRef.Services == nil { - j.platform.Status.ClusterPlatformRef.Services = &operatorapi.PlatformServicesStatus{} - } - j.platform.Status.ClusterPlatformRef.Services.JobServiceRef = &operatorapi.PlatformServiceRefStatus{ - Url: psJS.GetLocalServiceBaseUrl(), - } - } - } -} - -func (j JobServiceHandler) SetServiceUrlInWorkflowStatus(workflow *operatorapi.SonataFlow) { - if !profiles.IsDevProfile(workflow) && j.IsServiceEnabled() { - if workflow.Status.Services == nil { - workflow.Status.Services = &operatorapi.PlatformServicesStatus{} - } - workflow.Status.Services.JobServiceRef = &operatorapi.PlatformServiceRefStatus{ - Url: j.GetServiceBaseUrl(), - } - } -} - -func (j JobServiceHandler) IsServiceSetInSpec() bool { - return isJobServiceSet(j.platform) -} - -func (j *JobServiceHandler) IsServiceEnabledInSpec() bool { - return isJobServiceEnabled(j.platform) -} - -func (j JobServiceHandler) IsPersistenceEnabledtInSpec() bool { - return j.IsServiceSetInSpec() && j.platform.Spec.Services.JobService.Persistence != nil -} - -func (j *JobServiceHandler) isServiceEnabledInStatus() bool { - return j.platform != nil && j.platform.Status.ClusterPlatformRef != nil && - j.platform.Status.ClusterPlatformRef.Services != nil && j.platform.Status.ClusterPlatformRef.Services.JobServiceRef != nil && - !isServicesSet(j.platform) -} - -func (j *JobServiceHandler) IsServiceEnabled() bool { - return j.IsServiceEnabledInSpec() || j.isServiceEnabledInStatus() -} - -func (j *JobServiceHandler) GetServiceBaseUrl() string { - if j.IsServiceEnabledInSpec() { - return j.GetLocalServiceBaseUrl() - } - if j.isServiceEnabledInStatus() { - return j.platform.Status.ClusterPlatformRef.Services.JobServiceRef.Url - } - return "" -} - -func (j *JobServiceHandler) GetLocalServiceBaseUrl() string { - return GenerateServiceURL(constants.DefaultHTTPProtocol, j.platform.Namespace, j.GetServiceName()) -} - -func (j *JobServiceHandler) GetEnvironmentVariables() []corev1.EnvVar { - return []corev1.EnvVar{} -} - -func (j *JobServiceHandler) GetPodResourceRequirements() corev1.ResourceRequirements { - return corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("250m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("1Gi"), - }, - } -} - -func (j *JobServiceHandler) GetReplicaCount() int32 { - if j.platform.Spec.Services.JobService.PodTemplate.Replicas != nil && *j.platform.Spec.Services.JobService.PodTemplate.Replicas == 0 { - return 0 - } - return 1 -} - -func (j *JobServiceHandler) GetDeploymentStrategy() appsv1.DeploymentStrategy { - return appsv1.DeploymentStrategy{ - Type: appsv1.RecreateDeploymentStrategyType, - RollingUpdate: nil, - } -} - -func (j JobServiceHandler) MergeContainerSpec(containerSpec *corev1.Container) (*corev1.Container, error) { - return mergeContainerSpec(containerSpec, &j.platform.Spec.Services.JobService.PodTemplate.Container) -} - -// hasPostgreSQLConfigured returns true when either the SonataFlow Platform PostgreSQL CR's structure or the one in the Job service specification is not nil -func (j *JobServiceHandler) hasPostgreSQLConfigured() bool { - return j.IsServiceSetInSpec() && - ((j.platform.Spec.Services.JobService.Persistence != nil && j.platform.Spec.Services.JobService.Persistence.PostgreSQL != nil) || - (j.platform.Spec.Persistence != nil && j.platform.Spec.Persistence.PostgreSQL != nil)) -} - -func (j *JobServiceHandler) ConfigurePersistence(containerSpec *corev1.Container) *corev1.Container { - - if j.hasPostgreSQLConfigured() { - c := containerSpec.DeepCopy() - c.Image = j.GetServiceImageName(constants.PersistenceTypePostgreSQL) - p := persistence.RetrievePostgreSQLConfiguration(j.platform.Spec.Services.JobService.Persistence, j.platform.Spec.Persistence, j.GetServiceName()) - c.Env = append(c.Env, persistence.ConfigurePostgreSQLEnv(p.PostgreSQL, j.GetServiceName(), j.platform.Namespace, true)...) - - dbMigrationStrategyService := isDBMigrationStrategyService(j.platform.Spec.Services.JobService.Persistence) - - // Specific to Job Service - c.Env = append(c.Env, corev1.EnvVar{Name: quarkusFlywayMigrateAtStart, Value: dbMigrationStrategyService}) - c.Env = append(c.Env, corev1.EnvVar{Name: kogitoJobsServiceLoadJobsErrorStrategy, Value: "FAIL_SERVICE"}) - return c - } - return containerSpec -} - -func (j *JobServiceHandler) MergePodSpec(podSpec corev1.PodSpec) (corev1.PodSpec, error) { - c := podSpec.DeepCopy() - err := mergo.Merge(c, j.platform.Spec.Services.JobService.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride) - return *c, err -} - -func (j *JobServiceHandler) GenerateServiceProperties() (*properties.Properties, error) { - props := properties.NewProperties() - props.Set(constants.KogitoServiceURLProperty, GenerateServiceURL(constants.KogitoServiceURLProtocol, j.platform.Namespace, j.GetServiceName())) - props.Set(constants.JobServiceKafkaSmallRyeHealthProperty, "false") - props.Set(constants.JobServiceLeaderLivenessSmallRyeHealthProperty, "true") - props.Set(constants.JobServiceLeaderCheckExpirationInSeconds, constants.DefaultJobServiceLeaderCheckExpirationInSeconds) - - if j.GetServiceSource() == nil { - props.Set(constants.JobServiceKSinkInjectionHealthCheck, "false") - } else { - props.Set(constants.JobServiceKSinkInjectionHealthCheck, "true") - } - - if isDataIndexEnabled(j.platform) { - props.Set(constants.JobServiceStatusChangeEvents, "true") - if j.GetServiceSource() == nil { - di := NewDataIndexHandler(j.platform) - props.Set(constants.JobServiceStatusChangeEventsURL, di.GetLocalServiceBaseUrl()+"/jobs") - } else { - props.Set(constants.JobServiceStatusChangeEventsURL, constants.KnativeInjectedEnvVar) - props.Set(constants.JobServiceStatusChangeEventsConnector, constants.QuarkusHTTP) - props.Set(constants.JobServiceStatusChangeEventsMethod, constants.Post) - } - } - props.Sort() - return props, nil -} - -func SetServiceUrlsInWorkflowStatus(pl *operatorapi.SonataFlowPlatform, workflow *operatorapi.SonataFlow) { - tpsDI := NewDataIndexHandler(pl) - tpsJS := NewJobServiceHandler(pl) - - workflow.Status.Services = nil - tpsDI.SetServiceUrlInWorkflowStatus(workflow) - tpsJS.SetServiceUrlInWorkflowStatus(workflow) -} - -func (j *JobServiceHandler) GetServiceSource() *duckv1.Destination { - if j.platform.Spec.Services.JobService.Source != nil { - return j.platform.Spec.Services.JobService.Source - } - return GetPlatformBroker(j.platform) -} - -func (j *JobServiceHandler) GetServiceSink() *duckv1.Destination { - if j.platform.Spec.Services.JobService.Sink != nil { - return j.platform.Spec.Services.JobService.Sink - } - return GetPlatformBroker(j.platform) -} - -func isDataIndexEnabled(platform *operatorapi.SonataFlowPlatform) bool { - return isDataIndexSet(platform) && platform.Spec.Services.DataIndex.Enabled != nil && - *platform.Spec.Services.DataIndex.Enabled -} - -func isJobServiceEnabled(platform *operatorapi.SonataFlowPlatform) bool { - return isJobServiceSet(platform) && platform.Spec.Services.JobService.Enabled != nil && - *platform.Spec.Services.JobService.Enabled -} - -func isDataIndexSet(platform *operatorapi.SonataFlowPlatform) bool { - return isServicesSet(platform) && platform.Spec.Services.DataIndex != nil -} - -func isJobServiceSet(platform *operatorapi.SonataFlowPlatform) bool { - return isServicesSet(platform) && platform.Spec.Services.JobService != nil -} - -func isServicesSet(platform *operatorapi.SonataFlowPlatform) bool { - return platform != nil && platform.Spec.Services != nil -} - -func GenerateServiceURL(protocol string, namespace string, name string) string { - var serviceUrl string - if len(namespace) > 0 { - serviceUrl = fmt.Sprintf("%s://%s.%s", protocol, name, namespace) - } else { - serviceUrl = fmt.Sprintf("%s://%s", protocol, name) - } - return serviceUrl -} - -// mergeContainerSpec Produces the merging between the operatorapi.ContainerSpec provided in a SonataFlowPlatform -// service, for example, platform.services.jobsService.podTemplate.container, and the destination container for the -// corresponding service deployment. This method consider specific processing like not overriding environment vars -// already configured by the operator in the destination container. -func mergeContainerSpec(dest *corev1.Container, sourceSpec *operatorapi.ContainerSpec) (*corev1.Container, error) { - result := dest.DeepCopy() - source := sourceSpec.ToContainer() - err := mergeContainerPreservingEnvVars(result, &source) - return result, err -} - -// mergeContainerSpecPreservingEnvVars Merges the source container into the dest container by giving priority to the -// env variables already configured in the dest container when both containers have the same variable name. -func mergeContainerPreservingEnvVars(dest *corev1.Container, source *corev1.Container) error { - currentEnv := dest.Env - if err := mergo.Merge(dest, source, mergo.WithOverride); err != nil { - return err - } - dest.Env = currentEnv - for _, envVar := range source.Env { - kubernetes.AddEnvIfNotPresent(dest, envVar) - } - return nil -} - -// GetPlatformBroker gets the default broker for the platform. -func GetPlatformBroker(platform *operatorapi.SonataFlowPlatform) *duckv1.Destination { - if platform != nil && platform.Spec.Eventing != nil && platform.Spec.Eventing.Broker != nil { - return platform.Spec.Eventing.Broker - } - return nil -} - -func (d *DataIndexHandler) GetSourceBroker() *duckv1.Destination { - if d.platform != nil && d.platform.Spec.Services.DataIndex.Source != nil && d.platform.Spec.Services.DataIndex.Source.Ref != nil { - return d.platform.Spec.Services.DataIndex.Source - } - return GetPlatformBroker(d.platform) -} - -func (d *DataIndexHandler) newTrigger(labels map[string]string, annotations map[string]string, brokerName, namespace, serviceName, tag, eventType, path string, platform *operatorapi.SonataFlowPlatform) *eventingv1.Trigger { - return &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: kmeta.ChildName(fmt.Sprintf("data-index-%s-", tag), string(platform.GetUID())), - Namespace: namespace, - Labels: labels, - Annotations: annotations, - }, - Spec: eventingv1.TriggerSpec{ - Broker: brokerName, - Filter: &eventingv1.TriggerFilter{ - Attributes: eventingv1.TriggerFilterAttributes{ - "type": eventType, - }, - }, - Subscriber: duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: serviceName, - Namespace: platform.Namespace, - APIVersion: "v1", - Kind: "Service", - }, - URI: &apis.URL{ - Path: path, - }, - }, - }, - } -} -func (d *DataIndexHandler) GenerateKnativeResources(platform *operatorapi.SonataFlowPlatform, lbl map[string]string) ([]client.Object, *corev1.Event, error) { - broker := d.GetSourceBroker() - if broker == nil || len(broker.Ref.Name) == 0 { - return nil, nil, nil // Nothing to do - } - brokerName := broker.Ref.Name - namespace := broker.Ref.Namespace - if len(namespace) == 0 { - namespace = platform.Namespace - } - var brokerObject *eventingv1.Broker - var err error - if brokerObject, err = knative.ValidateBroker(brokerName, namespace); err != nil { - event := &corev1.Event{ - Type: corev1.EventTypeWarning, - Reason: WaitingKnativeEventing, - Message: fmt.Sprintf("%s for service: %s", err.Error(), d.GetServiceName()), - } - return nil, event, err - } - annotations := make(map[string]string) - managedAnnotations := make(map[string]string) - addTriggerAnnotations(knative.GetBrokerClass(brokerObject), managedAnnotations) - serviceName := d.GetServiceName() - return []client.Object{ - d.newTrigger(lbl, annotations, brokerName, namespace, serviceName, "process-error", "ProcessInstanceErrorDataEvent", constants.KogitoProcessInstancesEventsPath, platform), - d.newTrigger(lbl, annotations, brokerName, namespace, serviceName, "process-node", "ProcessInstanceNodeDataEvent", constants.KogitoProcessInstancesEventsPath, platform), - d.newTrigger(lbl, annotations, brokerName, namespace, serviceName, "process-state", "ProcessInstanceStateDataEvent", constants.KogitoProcessInstancesEventsPath, platform), - d.newTrigger(lbl, annotations, brokerName, namespace, serviceName, "process-variable", "ProcessInstanceVariableDataEvent", constants.KogitoProcessInstancesEventsPath, platform), - d.newTrigger(lbl, managedAnnotations, brokerName, namespace, serviceName, "process-definition", "ProcessDefinitionEvent", constants.KogitoProcessDefinitionsEventsPath, platform), - d.newTrigger(lbl, annotations, brokerName, namespace, serviceName, "process-instance-multiple", "MultipleProcessInstanceDataEvent", constants.KogitoProcessInstancesMultiEventsPath, platform), - d.newTrigger(lbl, managedAnnotations, brokerName, namespace, serviceName, "jobs", "JobEvent", constants.KogitoJobsPath, platform)}, nil, nil -} - -func (d JobServiceHandler) GetSourceBroker() *duckv1.Destination { - if d.platform.Spec.Services.JobService.Source != nil && d.platform.Spec.Services.JobService.Source.Ref != nil { - return d.platform.Spec.Services.JobService.Source - } - return GetPlatformBroker(d.platform) -} - -func addTriggerAnnotations(brokerClass string, annotations map[string]string) { - if knative.IsKafkaBroker(brokerClass) { - annotations[knative.KafkaKnativeEventingDeliveryOrder] = knative.KafkaKnativeEventingDeliveryOrderOrdered - } -} - -func (d JobServiceHandler) GetSink() *duckv1.Destination { - if d.platform.Spec.Services.JobService.Sink != nil { - return d.platform.Spec.Services.JobService.Sink - } - return GetPlatformBroker(d.platform) -} - -func (j *JobServiceHandler) GenerateKnativeResources(platform *operatorapi.SonataFlowPlatform, lbl map[string]string) ([]client.Object, *corev1.Event, error) { - broker := j.GetSourceBroker() - sink := j.GetSink() - resultObjs := []client.Object{} - - if broker != nil && len(broker.Ref.Name) > 0 { - brokerName := broker.Ref.Name - namespace := broker.Ref.Namespace - if len(namespace) == 0 { - namespace = platform.Namespace - } - var brokerObject *eventingv1.Broker - var err error - if brokerObject, err = knative.ValidateBroker(brokerName, namespace); err != nil { - event := &corev1.Event{ - Type: corev1.EventTypeWarning, - Reason: WaitingKnativeEventing, - Message: fmt.Sprintf("%s for service: %s", err.Error(), j.GetServiceName()), - } - return nil, event, err - } - annotations := make(map[string]string) - addTriggerAnnotations(knative.GetBrokerClass(brokerObject), annotations) - jobCreateTrigger := &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: kmeta.ChildName("jobs-service-create-job-", string(platform.GetUID())), - Namespace: namespace, - Labels: lbl, - Annotations: annotations, - }, - Spec: eventingv1.TriggerSpec{ - Broker: brokerName, - Filter: &eventingv1.TriggerFilter{ - Attributes: eventingv1.TriggerFilterAttributes{ - "type": "job.create", - }, - }, - Subscriber: duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: j.GetServiceName(), - Namespace: platform.Namespace, - APIVersion: "v1", - Kind: "Service", - }, - URI: &apis.URL{ - Path: constants.JobServiceJobEventsPath, - }, - }, - }, - } - resultObjs = append(resultObjs, jobCreateTrigger) - jobDeleteTrigger := &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: kmeta.ChildName("jobs-service-delete-job-", string(platform.GetUID())), - Namespace: namespace, - Labels: lbl, - Annotations: annotations, - }, - Spec: eventingv1.TriggerSpec{ - Broker: brokerName, - Filter: &eventingv1.TriggerFilter{ - Attributes: eventingv1.TriggerFilterAttributes{ - "type": "job.delete", - }, - }, - Subscriber: duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: j.GetServiceName(), - Namespace: platform.Namespace, - APIVersion: "v1", - Kind: "Service", - }, - URI: &apis.URL{ - Path: constants.JobServiceJobEventsPath, - }, - }, - }, - } - resultObjs = append(resultObjs, jobDeleteTrigger) - } - if sink != nil { - sinkBinding := &sourcesv1.SinkBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-jobs-service-sb", platform.Name), - Namespace: platform.Namespace, - Labels: lbl, - }, - Spec: sourcesv1.SinkBindingSpec{ - SourceSpec: duckv1.SourceSpec{ - Sink: *sink, - }, - BindingSpec: duckv1.BindingSpec{ - Subject: tracker.Reference{ - Name: j.GetServiceName(), - Namespace: platform.Namespace, - APIVersion: "apps/v1", - Kind: "Deployment", - }, - }, - }, - } - resultObjs = append(resultObjs, sinkBinding) - } - return resultObjs, nil, nil -} - -func (j *JobServiceHandler) CheckKSinkInjected() (bool, error) { - if j.GetSink() != nil { //job services has sink configured - return knative.CheckKSinkInjected(j.GetServiceName(), j.platform.Namespace) - } - return true, nil -} - -func IsDataIndexEnabled(plf *operatorapi.SonataFlowPlatform) bool { - if plf.Spec.Services != nil { - if plf.Spec.Services.DataIndex != nil { - return pointer.BoolDeref(plf.Spec.Services.DataIndex.Enabled, false) - } - return false - } - // Check if DataIndex is enabled in the platform status - if plf.Status.ClusterPlatformRef != nil && plf.Status.ClusterPlatformRef.Services != nil && plf.Status.ClusterPlatformRef.Services.DataIndexRef != nil && len(plf.Status.ClusterPlatformRef.Services.DataIndexRef.Url) > 0 { - return true - } - return false -} - -func IsJobServiceEnabled(plf *operatorapi.SonataFlowPlatform) bool { - if plf.Spec.Services != nil { - if plf.Spec.Services.JobService != nil { - return pointer.BoolDeref(plf.Spec.Services.JobService.Enabled, false) - } - return false - } - // Check if JobService is enabled in the platform status - if plf.Status.ClusterPlatformRef != nil && plf.Status.ClusterPlatformRef.Services != nil && plf.Status.ClusterPlatformRef.Services.JobServiceRef != nil && len(plf.Status.ClusterPlatformRef.Services.JobServiceRef.Url) > 0 { - return true - } - return false -} diff --git a/internal/controller/platform/services/services_suite_test.go b/internal/controller/platform/services/services_suite_test.go deleted file mode 100644 index 0a4e1019..00000000 --- a/internal/controller/platform/services/services_suite_test.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 services - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestServices(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Services Suite") -} diff --git a/internal/controller/platform/services/services_test.go b/internal/controller/platform/services/services_test.go deleted file mode 100644 index d79dd89b..00000000 --- a/internal/controller/platform/services/services_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 services - -import ( - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func TestMergeContainerSpec(t *testing.T) { - container := &corev1.Container{ - Env: []corev1.EnvVar{{Name: "var1", Value: "value1"}, {Name: "var2", Value: "value2"}}, - } - containerSpec := &operatorapi.ContainerSpec{ - Env: []corev1.EnvVar{{Name: "var1", Value: "value1Changed"}, {Name: "var3", Value: "value3"}}, - } - result, err := mergeContainerSpec(container, containerSpec) - assert.Nil(t, err) - assert.Len(t, result.Env, 3) - assert.Equal(t, result.Env[0], corev1.EnvVar{Name: "var1", Value: "value1"}) - assert.Equal(t, result.Env[1], corev1.EnvVar{Name: "var2", Value: "value2"}) - assert.Equal(t, result.Env[2], corev1.EnvVar{Name: "var3", Value: "value3"}) -} - -func TestMergeContainerPreservingEnvVars(t *testing.T) { - container1 := &corev1.Container{ - Env: []corev1.EnvVar{{Name: "var1", Value: "value1"}, {Name: "var2", Value: "value2"}}, - } - container2 := &corev1.Container{ - Env: []corev1.EnvVar{{Name: "var1", Value: "value1Changed"}, {Name: "var3", Value: "value3"}}, - } - err := mergeContainerPreservingEnvVars(container1, container2) - assert.Nil(t, err) - assert.Len(t, container1.Env, 3) - assert.Equal(t, container1.Env[0], corev1.EnvVar{Name: "var1", Value: "value1"}) - assert.Equal(t, container1.Env[1], corev1.EnvVar{Name: "var2", Value: "value2"}) - assert.Equal(t, container1.Env[2], corev1.EnvVar{Name: "var3", Value: "value3"}) -} diff --git a/internal/controller/platform/testdata/platformTest.Dockerfile b/internal/controller/platform/testdata/platformTest.Dockerfile deleted file mode 100644 index dd8a8591..00000000 --- a/internal/controller/platform/testdata/platformTest.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -FROM host/namespace/image:latest AS builder - -# Kogito User -USER 1001 - -# User home from base image -WORKDIR /home/kogito/kogito-base - -# Copy from build context to skeleton resources project -COPY --chown=1001 ../../../../test/builder ./src/main/resources - -# Maven vars enhirited from the base image -RUN ${MAVEN_HOME}/bin/mvn -U -B ${MAVEN_ARGS_APPEND} -s ${MAVEN_SETTINGS_PATH} clean install -DskipTests - -#============================= -# Runtime Run -#============================= -FROM registry.access.redhat.com/ubi9/openjdk-17:latest - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --from=builder --chown=185 /home/kogito/kogito-base/target/quarkus-app/lib/ /deployments/lib/ -COPY --from=builder --chown=185 /home/kogito/kogito-base/target/quarkus-app/*.jar /deployments/ -COPY --from=builder --chown=185 /home/kogito/kogito-base/target/quarkus-app/app/ /deployments/app/ -COPY --from=builder --chown=185 /home/kogito/kogito-base/target/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 185 -ENV AB_JOLOKIA_OFF="" -ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/internal/controller/platform/warm.go b/internal/controller/platform/warm.go deleted file mode 100644 index 1f2840c6..00000000 --- a/internal/controller/platform/warm.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 platform - -import ( - "context" - "errors" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -func NewWarmAction(reader ctrl.Reader) Action { - return &warmAction{ - reader: reader, - } -} - -type warmAction struct { - baseAction - reader ctrl.Reader -} - -func (action *warmAction) Name() string { - return "warm" -} - -func (action *warmAction) CanHandle(platform *operatorapi.SonataFlowPlatform) bool { - return platform.Status.IsWarming() -} - -func (action *warmAction) Handle(ctx context.Context, platform *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, *corev1.Event, error) { - // Check Kaniko warmer pod status - pod := corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: platform.Namespace, - Name: platform.Name + "-cache", - }, - } - - err := action.reader.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, &pod) - if err != nil { - return nil, nil, err - } - - switch pod.Status.Phase { - case corev1.PodSucceeded: - klog.V(log.D).InfoS("Kaniko cache successfully warmed up") - platform.Status.Manager().MarkTrueWithReason(api.SucceedConditionType, operatorapi.PlatformWarmingReason, "Kaniko cache successfully warmed up") - return platform, nil, nil - case corev1.PodFailed: - return nil, nil, errors.New("failed to warm up Kaniko cache") - default: - klog.V(log.I).InfoS("Waiting for Kaniko cache to warm up...") - // Requeue - return nil, nil, nil - } -} diff --git a/internal/controller/profiles/common/constants/objects.go b/internal/controller/profiles/common/constants/objects.go deleted file mode 100644 index d89cffc9..00000000 --- a/internal/controller/profiles/common/constants/objects.go +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 constants - -const ( - QuarkusHealthPathReady = "/q/health/ready" - QuarkusHealthPathLive = "/q/health/live" - - // Quarkus Health Check Probe configuration. - // See: https://quarkus.io/guides/smallrye-health#running-the-health-check - QuarkusHealthPathStarted = "/q/health/started" -) diff --git a/internal/controller/profiles/common/constants/platform_services.go b/internal/controller/profiles/common/constants/platform_services.go deleted file mode 100644 index 38b6d4d2..00000000 --- a/internal/controller/profiles/common/constants/platform_services.go +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 constants - -const ( - QuarkusHTTP = "quarkus-http" - Post = "POST" - DefaultHTTPProtocol = "http" - ConfigMapWorkflowPropsVolumeName = "workflow-properties" - - JobServiceRequestEventsURL = "mp.messaging.outgoing.kogito-job-service-job-request-events.url" - JobServiceRequestEventsConnector = "mp.messaging.outgoing.kogito-job-service-job-request-events.connector" - JobServiceRequestEventsMethod = "mp.messaging.outgoing.kogito-job-service-job-request-events.method" - JobServiceStatusChangeEvents = "kogito.jobs-service.http.job-status-change-events" - JobServiceStatusChangeEventsURL = "mp.messaging.outgoing.kogito-job-service-job-status-events-http.url" - JobServiceStatusChangeEventsConnector = "mp.messaging.outgoing.kogito-job-service-job-status-events-http.connector" - JobServiceStatusChangeEventsMethod = "mp.messaging.outgoing.kogito-job-service-job-status-events-http.method" - JobServiceURLProtocol = "http" - JobServiceDataSourceReactiveURL = "quarkus.datasource.reactive.url" - JobServiceJobEventsPath = "/v2/jobs/events" - JobServiceLeaderCheckExpirationInSeconds = "kogito.jobs-service.management.leader-check.expiration-in-seconds" - DefaultJobServiceLeaderCheckExpirationInSeconds = "60" - - KogitoProcessInstancesEventsConnector = "mp.messaging.outgoing.kogito-processinstances-events.connector" - KogitoProcessInstancesEventsMethod = "mp.messaging.outgoing.kogito-processinstances-events.method" - KogitoProcessInstancesEventsURL = "mp.messaging.outgoing.kogito-processinstances-events.url" - KogitoProcessInstancesEventsEnabled = "kogito.events.processinstances.enabled" - KogitoProcessInstancesEventsPath = "/processes" - // KogitoProcessInstancesMultiEventsPath Same value as KogitoProcessInstancesEventsPath intentionally - KogitoProcessInstancesMultiEventsPath = "/processes" - KogitoProcessDefinitionsEventsConnector = "mp.messaging.outgoing.kogito-processdefinitions-events.connector" - KogitoProcessDefinitionsEventsMethod = "mp.messaging.outgoing.kogito-processdefinitions-events.method" - KogitoProcessDefinitionsEventsURL = "mp.messaging.outgoing.kogito-processdefinitions-events.url" - KogitoProcessDefinitionsEventsEnabled = "kogito.events.processdefinitions.enabled" - KogitoProcessDefinitionsEventsErrorsEnabled = "kogito.events.processdefinitions.errors.propagate" - KogitoProcessDefinitionsEventsPath = "/definitions" - KogitoUserTasksEventsEnabled = "kogito.events.usertasks.enabled" - KogitoJobsPath = "/jobs" - // KogitoDataIndexHealthCheckEnabled configures if a workflow must check for the data index availability as part - // of its start health check. - KogitoDataIndexHealthCheckEnabled = "kogito.data-index.health-enabled" - // KogitoDataIndexURL configures the data index url, this value can be used internally by the workflow. - KogitoDataIndexURL = "kogito.data-index.url" - - // KogitoJobServiceHealthCheckEnabled configures if a workflow must check for the job service availability as part - // of its start health check. - KogitoJobServiceHealthCheckEnabled = "kogito.jobs-service.health-enabled" - // KogitoJobServiceURL configures the jobs service, this value can be used internally by the workflow. - KogitoJobServiceURL = "kogito.jobs-service.url" - KogitoServiceURLProperty = "kogito.service.url" - KogitoServiceURLProtocol = "http" - DataIndexKafkaSmallRyeHealthProperty = `quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled` - JobServiceKafkaSmallRyeHealthProperty = `quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled` - JobServiceLeaderLivenessSmallRyeHealthProperty = `quarkus.smallrye-health.check."org.kie.kogito.jobs.service.management.JobServiceLeaderLivenessHealthCheck".enabled` - DataIndexKafkaHealthCheck = `quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled` - JobServiceKSinkInjectionHealthCheck = `quarkus.smallrye-health.check."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled` - - DataIndexServiceName = "data-index-service" - JobServiceName = "jobs-service" - ImageNamePrefix = "docker.io/apache/incubator-kie-kogito" - DataIndexName = "data-index" - KogitoDBMigratorTool = "db-migrator-tool" - - DefaultPostgresServiceName string = "postgresql" - DefaultDatabaseName string = "sonataflow" - DefaultPostgreSQLPort int = 5432 -) - -type PersistenceType string - -const ( - PersistenceTypePostgreSQL PersistenceType = "postgresql" - PersistenceTypeEphemeral PersistenceType = "ephemeral" -) - -func (p PersistenceType) String() string { - return string(p) -} diff --git a/internal/controller/profiles/common/constants/reconcile.go b/internal/controller/profiles/common/constants/reconcile.go deleted file mode 100644 index fb86e55b..00000000 --- a/internal/controller/profiles/common/constants/reconcile.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 constants - -import "time" - -const ( - RequeueAfterFailure = 3 * time.Minute - RequeueAfterFollowDeployment = 5 * time.Second - RequeueAfterIsRunning = 1 * time.Minute - // RecoverDeploymentErrorRetries how many times the operator should try to recover from a failure before giving up - RecoverDeploymentErrorRetries = 3 - // RequeueRecoverDeploymentErrorInterval interval between recovering from failures - RequeueRecoverDeploymentErrorInterval = RecoverDeploymentErrorInterval * time.Minute - RecoverDeploymentErrorInterval = 10 - DefaultHTTPWorkflowPortInt = 8080 - // MaxWorkflowFinalizerAttempts how many times the operator will try to execute a SonataFlow CRD finalizer. - MaxWorkflowFinalizerAttempts = 3 - // WorkflowFinalizerRetryInterval interval between SonataFlow CRD finalizer execution attempts. - WorkflowFinalizerRetryInterval = 5 * time.Second - // WorkflowFinalizerSchedulingRetryInterval interval for the operator to retry to schedule a failing finalizer scheduling. - WorkflowFinalizerSchedulingRetryInterval = 5 * time.Second - // EventDeliveryTimeout delivery timeout for the cloud events produced by the operator. - EventDeliveryTimeout = 30 * time.Second -) diff --git a/internal/controller/profiles/common/constants/workflows.go b/internal/controller/profiles/common/constants/workflows.go deleted file mode 100644 index d9368782..00000000 --- a/internal/controller/profiles/common/constants/workflows.go +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 constants - -const ( - KogitoOutgoingEventsURL = "mp.messaging.outgoing.kogito_outgoing_stream.url" - KogitoOutgoingEventsConnector = "mp.messaging.outgoing.kogito_outgoing_stream.connector" - KogitoIncomingEventsConnector = "mp.messaging.incoming.kogito_incoming_stream.connector" - KogitoIncomingEventsPath = "mp.messaging.incoming.kogito_incoming_stream.path" - KnativeHealthEnabled = "org.kie.kogito.addons.knative.eventing.health-enabled" - KnativeInjectedEnvVar = "${K_SINK}" - TriggerFinalizer = "trigger-deletion" - WorkflowFinalizer = "workflow-deletion" - QuarkusDevUICorsEnabled = "quarkus.dev-ui.cors.enabled" - QuarkusDevUIHosts = "quarkus.dev-ui.hosts" - KogitoEventsGrouping = "kogito.events.grouping" - KogitoEventsGroupingBinary = "kogito.events.grouping.binary" - KogitoEventsGroupingCompress = "kogito.events.grouping.compress" -) diff --git a/internal/controller/profiles/common/deployment_status_manager.go b/internal/controller/profiles/common/deployment_status_manager.go deleted file mode 100644 index f1302c53..00000000 --- a/internal/controller/profiles/common/deployment_status_manager.go +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -var _ WorkflowDeploymentManager = &deploymentHandler{} - -const knativeDeploymentSuffix = "-deployment" - -// WorkflowDeploymentManager interface to handle workflow deployment features. -type WorkflowDeploymentManager interface { - // SyncDeploymentStatus updates the workflow status aligned with the deployment counterpart. - // For example, if the deployment is in a failed state, it sets the status to - // Running `false` and the Message and Reason to human-readable format. - SyncDeploymentStatus(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) - // RolloutDeployment rolls out the underlying deployment object for the given workflow. - RolloutDeployment(ctx context.Context, workflow *operatorapi.SonataFlow) error -} - -// DeploymentManager creates a new WorkflowDeploymentManager implementation based on the current profile. -func DeploymentManager(c client.Client) WorkflowDeploymentManager { - return &deploymentHandler{c: c} -} - -type deploymentHandler struct { - c client.Client -} - -func (d *deploymentHandler) getDeployment(ctx context.Context, workflow *operatorapi.SonataFlow) (*appsv1.Deployment, error) { - deploymentName := workflow.Name - if workflow.IsKnativeDeployment() { - ksvc := &servingv1.Service{} - if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow), ksvc); err != nil { - if errors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - deploymentName = ksvc.Status.LatestCreatedRevisionName + knativeDeploymentSuffix - } - deployment := &appsv1.Deployment{} - if err := d.c.Get(ctx, types.NamespacedName{Namespace: workflow.Namespace, Name: deploymentName}, deployment); err != nil { - if errors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - return deployment, nil -} - -func (d *deploymentHandler) RolloutDeployment(ctx context.Context, workflow *operatorapi.SonataFlow) error { - deployment, err := d.getDeployment(ctx, workflow) - if err != nil || deployment == nil { - return err - } - if err = kubeutil.MarkDeploymentToRollout(deployment); err != nil { - return err - } - return d.c.Update(ctx, deployment) -} - -func (d *deploymentHandler) SyncDeploymentStatus(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) { - deployment, err := d.getDeployment(ctx, workflow) - if err != nil || deployment == nil { - // we should have the deployment by this time, so even if the error above is not found, we should halt. - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, "Couldn't find the workflow deployment") - workflow.Status.SetReplicas(0) - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, err - } - - // Deployment is available, we can return after setting Running = TRUE - if kubeutil.IsDeploymentAvailable(deployment) { - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - workflow.Status.SetReplicas(deployment.Status.ReadyReplicas) - klog.V(log.I).InfoS("Workflow is in Running Condition") - return ctrl.Result{RequeueAfter: constants.RequeueAfterIsRunning}, nil - } - - if kubeutil.IsDeploymentFailed(deployment) { - // Fallback to a general failure message if we can't determine if the deployment has minimum replicas available. - failedReason := GetDeploymentUnavailabilityMessage(deployment) - workflow.Status.LastTimeRecoverAttempt = metav1.Now() - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentFailureReason, failedReason) - workflow.Status.SetReplicas(0) - klog.V(log.I).InfoS("Workflow deployment failed", "Reason Message", failedReason) - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil - } - - // Deployment hasn't minimum replicas, let's find out why to give users a meaningful information - if kubeutil.IsDeploymentMinimumReplicasUnavailable(deployment) { - message, err := kubeutil.DeploymentTroubleshooter(d.c, deployment, operatorapi.DefaultContainerName).ReasonMessage() - workflow.Status.SetReplicas(deployment.Status.ReadyReplicas) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, err - } - if len(message) > 0 { - klog.V(log.I).InfoS("Workflow is not in Running condition duo to a deployment unavailability issue", "reason", message) - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, message) - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil - } - } - - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForDeploymentReason, "") - workflow.Status.SetReplicas(deployment.Status.ReadyReplicas) - klog.V(log.I).InfoS("Workflow is in WaitingForDeployment Condition") - return ctrl.Result{RequeueAfter: constants.RequeueAfterFollowDeployment, Requeue: true}, nil -} - -// GetDeploymentUnavailabilityMessage gets the replica failure reason. -// MUST be called after checking that the Deployment is NOT available. -// If there's no reason, the Deployment state has no apparent reason to be in failed state. -func GetDeploymentUnavailabilityMessage(deployment *appsv1.Deployment) string { - failure := kubeutil.GetDeploymentUnavailabilityMessage(deployment) - if len(failure) == 0 { - failure = fmt.Sprintf("Workflow Deployment %s is unavailable", deployment.Name) - } - return failure -} diff --git a/internal/controller/profiles/common/ensurer.go b/internal/controller/profiles/common/ensurer.go deleted file mode 100644 index 16f08e09..00000000 --- a/internal/controller/profiles/common/ensurer.go +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - - "k8s.io/klog/v2" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" -) - -var _ ObjectEnsurer = &defaultObjectEnsurer{} -var _ ObjectEnsurer = &noopObjectEnsurer{} -var _ ObjectsEnsurer = &defaultObjectsEnsurer{} - -type ObjectEnsurer interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) -} -type ObjectEnsurerWithPlatform interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) -} - -// MutateVisitor is a visitor function that mutates the given object before performing any updates in the cluster. -// It gets called after the objectEnforcer reference. -// -// The defaultObjectEnsurer will call the returned MutateVisitor function after creating the given object structure, -// so callers is ensured to have the default reference of the given object. -// -// Usually you can safely do `object.(*).Spec...` since you control the ObjectCreator. -// -// Example: `object.(*appsv1.Deployment).Spec.Template.Name="myApp"` to change the pod's name. -type MutateVisitor func(object client.Object) controllerutil.MutateFn - -// NewObjectEnsurer see defaultObjectEnsurer -func NewObjectEnsurer(client client.Client, creator ObjectCreator) ObjectEnsurer { - return &defaultObjectEnsurer{ - c: client, - creator: creator, - } -} - -// NewObjectEnsurerWithPlatform see defaultObjectEnsurerWithPLatform -func NewObjectEnsurerWithPlatform(client client.Client, creator ObjectCreatorWithPlatform) ObjectEnsurerWithPlatform { - return &defaultObjectEnsurerWithPlatform{ - c: client, - creator: creator, - } -} - -// defaultObjectEnsurer provides the engine for a ReconciliationState that needs to create or update a given Kubernetes object during the reconciliation cycle. -type defaultObjectEnsurer struct { - c client.Client - creator ObjectCreator -} - -func (d *defaultObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { - result := controllerutil.OperationResultNone - - object, err := d.creator(workflow) - if err != nil || object == nil { - return nil, result, err - } - return ensureObject(ctx, workflow, visitors, result, d.c, object) -} - -// defaultObjectEnsurerWithPlatform is the equivalent of defaultObjectEnsurer for resources that require a reference to the SonataFlowPlatform -type defaultObjectEnsurerWithPlatform struct { - c client.Client - creator ObjectCreatorWithPlatform -} - -func (d *defaultObjectEnsurerWithPlatform) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { - result := controllerutil.OperationResultNone - - object, err := d.creator(workflow, pl) - if err != nil { - return nil, result, err - } - if object == nil { - return nil, result, nil - } - if result, err = controllerutil.CreateOrPatch(ctx, d.c, object, - func() error { - for _, v := range visitors { - if visitorErr := v(object)(); visitorErr != nil { - return visitorErr - } - } - return controllerutil.SetControllerReference(workflow, object, d.c.Scheme()) - }); err != nil { - return nil, result, err - } - klog.V(log.I).InfoS("Object operation finalized", "result", result, "kind", object.GetObjectKind().GroupVersionKind().String(), "name", object.GetName(), "namespace", object.GetNamespace()) - return object, result, nil -} - -// NewNoopObjectEnsurer see noopObjectEnsurer -func NewNoopObjectEnsurer() ObjectEnsurer { - return &noopObjectEnsurer{} -} - -// noopObjectEnsurer is a useful Object ensurer to apply the null pattern. Use it when you need a creator that does nothing -type noopObjectEnsurer struct { -} - -func (d *noopObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { - result := controllerutil.OperationResultNone - return nil, result, nil -} - -// ObjectsEnsurer is an ensurer to apply multiple objects -type ObjectsEnsurer interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) []ObjectEnsurerResult -} - -type ObjectEnsurerResult struct { - client.Object - Result controllerutil.OperationResult - Error error -} - -// ObjectsEnsurer is an ensurer to apply multiple objects -type ObjectsEnsurerWithPlatform interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) []ObjectEnsurerResult -} - -func NewObjectsEnsurerWithPlatform(client client.Client, creator ObjectsCreatorWithPlatform) ObjectsEnsurerWithPlatform { - return &defaultObjectsEnsurerWithPlatform{ - c: client, - creator: creator, - } -} - -type defaultObjectsEnsurerWithPlatform struct { - ObjectsEnsurer - c client.Client - creator ObjectsCreatorWithPlatform -} - -func (d *defaultObjectsEnsurerWithPlatform) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) []ObjectEnsurerResult { - result := controllerutil.OperationResultNone - - objects, err := d.creator(workflow, pl) - if err != nil { - return []ObjectEnsurerResult{{nil, result, err}} - } - var ensureResult []ObjectEnsurerResult - for _, object := range objects { - ensureObject, c, err := ensureObject(ctx, workflow, visitors, result, d.c, object) - ensureResult = append(ensureResult, ObjectEnsurerResult{ensureObject, c, err}) - if err != nil { - return ensureResult - } - } - return ensureResult -} - -func NewObjectsEnsurer(client client.Client, creator ObjectsCreator) ObjectsEnsurer { - return &defaultObjectsEnsurer{ - c: client, - creator: creator, - } -} - -type defaultObjectsEnsurer struct { - ObjectsEnsurer - c client.Client - creator ObjectsCreator -} - -func (d *defaultObjectsEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) []ObjectEnsurerResult { - result := controllerutil.OperationResultNone - - objects, err := d.creator(workflow) - if err != nil { - return []ObjectEnsurerResult{{nil, result, err}} - } - var ensureResult []ObjectEnsurerResult - for _, object := range objects { - ensureObject, c, err := ensureObject(ctx, workflow, visitors, result, d.c, object) - ensureResult = append(ensureResult, ObjectEnsurerResult{ensureObject, c, err}) - if err != nil { - return ensureResult - } - } - return ensureResult -} - -func setWorkflowFinalizer(ctx context.Context, c client.Client, workflow *operatorapi.SonataFlow) error { - if !controllerutil.ContainsFinalizer(workflow, constants.TriggerFinalizer) { - controllerutil.AddFinalizer(workflow, constants.TriggerFinalizer) - return c.Update(ctx, workflow) - } - return nil -} - -func ensureObject(ctx context.Context, workflow *operatorapi.SonataFlow, visitors []MutateVisitor, result controllerutil.OperationResult, c client.Client, object client.Object) (client.Object, controllerutil.OperationResult, error) { - if result, err := controllerutil.CreateOrPatch(ctx, c, object, - func() error { - for _, v := range visitors { - if visitorErr := v(object)(); visitorErr != nil { - return visitorErr - } - } - if trigger, ok := object.(*eventingv1.Trigger); ok { - addToSonataFlowTriggerList(workflow, trigger) - if workflow.Namespace != object.GetNamespace() { - // This is for Knative trigger in a different namespace - // Set the finalizer for trigger cleanup when the workflow is deleted - return setWorkflowFinalizer(ctx, c, workflow) - } - } - return controllerutil.SetControllerReference(workflow, object, c.Scheme()) - }); err != nil { - return nil, result, err - } - klog.V(log.I).InfoS("Object operation finalized", "result", result, "kind", object.GetObjectKind().GroupVersionKind().String(), "name", object.GetName(), "namespace", object.GetNamespace()) - return object, result, nil -} - -func addToSonataFlowTriggerList(workflow *operatorapi.SonataFlow, trigger *eventingv1.Trigger) { - for _, t := range workflow.Status.Triggers { - if t.Name == trigger.Name && t.Namespace == trigger.Namespace { - return // trigger already exists - } - } - workflow.Status.Triggers = append(workflow.Status.Triggers, operatorapi.SonataFlowTriggerRef{Name: trigger.Name, Namespace: trigger.Namespace}) -} diff --git a/internal/controller/profiles/common/knative_eventing.go b/internal/controller/profiles/common/knative_eventing.go deleted file mode 100644 index 4455763e..00000000 --- a/internal/controller/profiles/common/knative_eventing.go +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 ( - "context" - - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/log" -) - -var _ KnativeEventingHandler = &knativeObjectManager{} - -type knativeObjectManager struct { - sinkBinding ObjectEnsurerWithPlatform - trigger ObjectsEnsurerWithPlatform - platform *operatorapi.SonataFlowPlatform - *StateSupport -} - -func NewKnativeEventingHandler(support *StateSupport, pl *operatorapi.SonataFlowPlatform) KnativeEventingHandler { - return &knativeObjectManager{ - sinkBinding: NewObjectEnsurerWithPlatform(support.C, SinkBindingCreator), - trigger: NewObjectsEnsurerWithPlatform(support.C, TriggersCreator), - platform: pl, - StateSupport: support, - } -} - -type KnativeEventingHandler interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) ([]client.Object, error) -} - -func (k knativeObjectManager) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) ([]client.Object, error) { - var objs []client.Object - - knativeAvail, err := knative.GetKnativeAvailability(k.Cfg) - if err != nil { - klog.V(log.I).InfoS("Error checking Knative Eventing: %v", err) - return nil, err - } - if !knativeAvail.Eventing { - klog.V(log.I).InfoS("Knative Eventing is not installed") - } else { - // create sinkBinding and trigger - sinkBinding, _, err := k.sinkBinding.Ensure(ctx, workflow, k.platform) - if err != nil { - return objs, err - } else if sinkBinding != nil { - objs = append(objs, sinkBinding) - } - - triggers := k.trigger.Ensure(ctx, workflow, k.platform) - for _, trigger := range triggers { - if trigger.Error != nil { - return objs, trigger.Error - } - objs = append(objs, trigger.Object) - } - } - return objs, nil -} diff --git a/internal/controller/profiles/common/mutate_visitors.go b/internal/controller/profiles/common/mutate_visitors.go deleted file mode 100644 index c19f35e4..00000000 --- a/internal/controller/profiles/common/mutate_visitors.go +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "maps" - "reflect" - "slices" - - "github.com/imdario/mergo" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/properties" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -// ImageDeploymentMutateVisitor creates a visitor that mutates a vanilla Kubernetes Deployment to apply the given image in the DefaultContainerName container -// Only overrides the image if .spec.podTemplate.container.Image is empty. -func ImageDeploymentMutateVisitor(workflow *operatorapi.SonataFlow, image string) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - // noop since we already have an image in the flow container defined by the user. - if workflow.HasContainerSpecImage() { - return func() error { - return nil - } - } - return func() error { - deployment := object.(*appsv1.Deployment) - _, idx := kubeutil.GetContainerByName(operatorapi.DefaultContainerName, &deployment.Spec.Template.Spec) - deployment.Spec.Template.Spec.Containers[idx].Image = image - deployment.Spec.Template.Spec.Containers[idx].ImagePullPolicy = kubeutil.GetImagePullPolicy(image) - return nil - } - } -} - -// ImageKServiceMutateVisitor same as ImageDeploymentMutateVisitor for Knative Serving -func ImageKServiceMutateVisitor(workflow *operatorapi.SonataFlow, image string) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - // noop since we already have an image in the flow container defined by the user. - if workflow.HasContainerSpecImage() { - return func() error { - return nil - } - } - return func() error { - ksvc := object.(*servingv1.Service) - _, idx := kubeutil.GetContainerByName(operatorapi.DefaultContainerName, &ksvc.Spec.Template.Spec.PodSpec) - ksvc.Spec.Template.Spec.Containers[idx].Image = image - ksvc.Spec.Template.Spec.Containers[idx].ImagePullPolicy = kubeutil.GetImagePullPolicy(image) - return nil - } - } -} - -// DeploymentMutateVisitor guarantees the state of the default Deployment object -func DeploymentMutateVisitor(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - if kubeutil.IsObjectNew(object) { - return nil - } - original, err := DeploymentCreator(workflow, plf) - if err != nil { - return err - } - src := original.(*appsv1.Deployment) - dst := object.(*appsv1.Deployment) - // merge new and old labels, but prevent overriding to keep exiting immutable selector working. - mergo.Merge(&dst.ObjectMeta.Labels, src.ObjectMeta.Labels, mergo.WithAppendSlice) - // to prevent furhter merge conflcts set the same lables on both src and dst - src.ObjectMeta.Labels = dst.ObjectMeta.Labels - if !maps.Equal(dst.Spec.Selector.MatchLabels, src.Spec.Selector.MatchLabels) { - // mutating selector labels is not supported so to prevent merge conflicts we set src and dst - // values to be identical - src.Spec.Selector.MatchLabels = dst.Spec.Selector.MatchLabels - } - if !slices.EqualFunc( - dst.Spec.Selector.MatchExpressions, - src.Spec.Selector.MatchExpressions, - func(lsr1, lsr2 metav1.LabelSelectorRequirement) bool { - return reflect.DeepEqual(lsr1, lsr2) - }) { - // mutating selector matchExpressions is not supported so to prevent merge conflicts we set src and dst - // values to be identical - src.Spec.Selector.MatchExpressions = dst.Spec.Selector.MatchExpressions - } - return EnsureDeployment(src, dst) - } - } -} - -// EnsureDeployment Ensure that the original Deployment fields are immutable. -func EnsureDeployment(original *appsv1.Deployment, object *appsv1.Deployment) error { - object.Spec.Replicas = original.Spec.Replicas - object.Spec.Selector = original.Spec.Selector - object.Labels = original.GetLabels() - object.Finalizers = original.Finalizers - - // Clean up the volumes, they are inherited from original, additional are added by other visitors - // However, the knative data (voulmes, volumes mounts) must be preserved - knative.SaveKnativeData(&original.Spec.Template.Spec, &object.Spec.Template.Spec) - object.Spec.Template.Spec.Volumes = nil - for i := range object.Spec.Template.Spec.Containers { - object.Spec.Template.Spec.Containers[i].VolumeMounts = nil - } - - // we do a merge to not keep changing the spec since k8s will set default values to the podSpec - return mergo.Merge(&object.Spec.Template.Spec, original.Spec.Template.Spec, mergo.WithOverride) -} - -// KServiceMutateVisitor guarantees the state of the default Knative Service object -func KServiceMutateVisitor(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - if kubeutil.IsObjectNew(object) { - return nil - } - original, err := KServiceCreator(workflow, plf) - if err != nil { - return err - } - return EnsureKService(original.(*servingv1.Service), object.(*servingv1.Service)) - } - } -} - -// EnsureKService Ensure that the original Knative Service fields are immutable. -func EnsureKService(original *servingv1.Service, object *servingv1.Service) error { - object.Labels = original.GetLabels() - - // Clean up the volumes, they are inherited from original, additional are added by other visitors - // However, the knative data (voulmes, volumes mounts) must be preserved - knative.SaveKnativeData(&original.Spec.Template.Spec.PodSpec, &object.Spec.Template.Spec.PodSpec) - object.Spec.Template.Spec.Volumes = nil - for i := range object.Spec.Template.Spec.Containers { - object.Spec.Template.Spec.Containers[i].VolumeMounts = nil - } - - // we do a merge to not keep changing the spec since k8s will set default values to the podSpec - return mergo.Merge(&object.Spec.Template.Spec.PodSpec, original.Spec.Template.Spec.PodSpec, mergo.WithOverride) -} - -func ServiceMutateVisitor(workflow *operatorapi.SonataFlow) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - if kubeutil.IsObjectNew(object) { - return nil - } - original, err := ServiceCreator(workflow) - if err != nil { - return err - } - object.(*corev1.Service).Spec.Ports = original.(*corev1.Service).Spec.Ports - object.(*corev1.Service).Labels = original.GetLabels() - return nil - } - } -} - -func ManagedPropertiesMutateVisitor(ctx context.Context, catalog discovery.ServiceCatalog, - workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform, userProps *corev1.ConfigMap) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - managedProps := object.(*corev1.ConfigMap) - managedProps.Labels = workflow.GetLabels() - _, hasKey := managedProps.Data[workflowproj.GetManagedPropertiesFileName(workflow)] - if !hasKey { - managedProps.Data = make(map[string]string, 1) - managedProps.Data[workflowproj.GetManagedPropertiesFileName(workflow)] = "" - } - - userProperties, hasKey := userProps.Data[workflowproj.ApplicationPropertiesFileName] - if !hasKey { - userProperties = "" - } - propertyHandler, err := properties.NewManagedPropertyHandler(workflow, plf) - if err != nil { - return err - } - managedProps.Data[workflowproj.GetManagedPropertiesFileName(workflow)] = propertyHandler.WithUserProperties(userProperties). - WithServiceDiscovery(ctx, catalog). - Build() - return nil - } - } -} - -// RolloutDeploymentIfCMChangedMutateVisitor forces a pod refresh if the workflow definition suffered any changes. -// This method can be used as an alternative to the Kubernetes ConfigMap refresher. -// -// See: https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically -func RolloutDeploymentIfCMChangedMutateVisitor(workflow *operatorapi.SonataFlow, userPropsCM *corev1.ConfigMap, managedPropsCM *corev1.ConfigMap) MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - deployment := object.(*appsv1.Deployment) - return kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM, managedPropsCM) - } - } -} - -func RestoreDeploymentVolumeAndVolumeMountMutateVisitor() MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - deployment := object.(*appsv1.Deployment) - knative.RestoreKnativeVolumeAndVolumeMount(&deployment.Spec.Template.Spec) - return nil - } - } -} - -func RestoreKServiceVolumeAndVolumeMountMutateVisitor() MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - service := object.(*servingv1.Service) - knative.RestoreKnativeVolumeAndVolumeMount(&service.Spec.Template.Spec.PodSpec) - return nil - } - } -} diff --git a/internal/controller/profiles/common/object_creators.go b/internal/controller/profiles/common/object_creators.go deleted file mode 100644 index aae6eb83..00000000 --- a/internal/controller/profiles/common/object_creators.go +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - "strings" - - policyv1 "k8s.io/api/policy/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - - "github.com/imdario/mergo" - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - duckv1 "knative.dev/pkg/apis/duck/v1" - "knative.dev/pkg/kmeta" - "knative.dev/pkg/tracker" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/properties" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/variables" - "github.com/kubesmarts/logic-operator/utils" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/utils/openshift" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -const ( - knativeServingAPIVersion = "serving.knative.dev/v1" - knativeServiceKind = "Service" - deploymentAPIVersion = "apps/v1" - deploymentKind = "Deployment" - k8sServiceAPIVersion = "v1" - k8sServiceKind = "Service" - k8sServicePortName = "web" - metricsServicePortPath = "/q/metrics" -) - -// ObjectCreator is the func that creates the initial reference object, if the object doesn't exist in the cluster, this one is created. -// Can be used as a reference to keep the object immutable -type ObjectCreator func(workflow *operatorapi.SonataFlow) (client.Object, error) - -// ObjectCreatorWithPlatform is the func equivalent to ObjectCreator to use when the resource being created needs a reference to the -// SonataFlowPlatform -type ObjectCreatorWithPlatform func(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (client.Object, error) - -// ObjectsCreator creates multiple resources -type ObjectsCreator func(workflow *operatorapi.SonataFlow) ([]client.Object, error) - -// ObjectsCreatorWithPlatform creates multiple resources -type ObjectsCreatorWithPlatform func(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) ([]client.Object, error) - -const ( - defaultHTTPServicePort = 80 - - // Default deployment health check configuration - // See: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ - - healthTimeoutSeconds = 3 - healthStartedFailureThreshold = 5 - healthStartedPeriodSeconds = 15 - healthStartedInitialDelaySeconds = 10 -) - -// DeploymentCreator is an objectCreator for a base Kubernetes Deployments for profiles that need to deploy the workflow on a vanilla deployment. -// It serves as a basis for a basic Quarkus Java application, expected to listen on http 8080. -func DeploymentCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - - deployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: GetReplicasOrDefault(workflow), - Selector: &metav1.LabelSelector{ - MatchLabels: workflowproj.GetSelectorLabels(workflow), - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: lbl, - }, - Spec: corev1.PodSpec{}, - }, - }, - } - - if err := mergo.Merge(&deployment.Spec.Template.Spec, workflow.Spec.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride); err != nil { - return nil, err - } - flowContainer, err := defaultContainer(workflow, plf) - if err != nil { - return nil, err - } - kubeutil.AddOrReplaceContainer(operatorapi.DefaultContainerName, *flowContainer, &deployment.Spec.Template.Spec) - - return deployment, nil -} - -// KServiceCreator creates the default Knative Service object for SonataFlow instances. It's based on the default DeploymentCreator. -func KServiceCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - ksvc := &servingv1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: servingv1.ServiceSpec{ - ConfigurationSpec: servingv1.ConfigurationSpec{ - Template: servingv1.RevisionTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: lbl, - }, - Spec: servingv1.RevisionSpec{ - PodSpec: corev1.PodSpec{}, - }, - }, - }, - }, - } - - if err := mergo.Merge(&ksvc.Spec.Template.Spec.PodSpec, workflow.Spec.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride); err != nil { - return nil, err - } - flowContainer, err := defaultContainer(workflow, plf) - if err != nil { - return nil, err - } - kubeutil.AddOrReplaceContainer(operatorapi.DefaultContainerName, *flowContainer, &ksvc.Spec.Template.Spec.PodSpec) - - return ksvc, nil -} - -func GetReplicasOrDefault(workflow *operatorapi.SonataFlow) *int32 { - var dReplicas int32 = 1 - if workflow.Spec.PodTemplate.Replicas == nil { - return &dReplicas - } - return workflow.Spec.PodTemplate.Replicas -} - -func defaultContainer(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (*corev1.Container, error) { - defaultContainerPort := corev1.ContainerPort{ - ContainerPort: variables.DefaultHTTPWorkflowPortIntStr.IntVal, - Name: utils.DefaultServicePortName, - Protocol: corev1.ProtocolTCP, - } - defaultFlowContainer := &corev1.Container{ - Name: operatorapi.DefaultContainerName, - Ports: []corev1.ContainerPort{defaultContainerPort}, - TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, - LivenessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: constants.QuarkusHealthPathLive, - Port: variables.DefaultHTTPWorkflowPortIntStr, - }, - }, - TimeoutSeconds: healthTimeoutSeconds, - PeriodSeconds: healthStartedPeriodSeconds, - }, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: constants.QuarkusHealthPathReady, - Port: variables.DefaultHTTPWorkflowPortIntStr, - }, - }, - TimeoutSeconds: healthTimeoutSeconds, - PeriodSeconds: healthStartedPeriodSeconds, - }, - StartupProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: constants.QuarkusHealthPathStarted, - Port: variables.DefaultHTTPWorkflowPortIntStr, - }, - }, - InitialDelaySeconds: healthStartedInitialDelaySeconds, - TimeoutSeconds: healthTimeoutSeconds, - FailureThreshold: healthStartedFailureThreshold, - PeriodSeconds: healthStartedPeriodSeconds, - }, - SecurityContext: kubeutil.SecurityDefaults(), - } - // Merge with flowContainer - if err := mergo.Merge(defaultFlowContainer, workflow.Spec.PodTemplate.Container.ToContainer(), mergo.WithOverride); err != nil { - return nil, err - } - if !profiles.IsDevProfile(workflow) { - var pper *operatorapi.PlatformPersistenceOptionsSpec - if plf != nil && plf.Spec.Persistence != nil { - pper = plf.Spec.Persistence - } - if p := persistence.RetrieveConfiguration(workflow.Spec.Persistence, pper, workflow.Name); p != nil { - defaultFlowContainer = persistence.ConfigureWorkflowPersistence(defaultFlowContainer, p, workflow.Name, workflow.Namespace) - } - } - // immutable - defaultFlowContainer.Name = operatorapi.DefaultContainerName - portIdx := -1 - for i := range defaultFlowContainer.Ports { - if defaultFlowContainer.Ports[i].Name == utils.DefaultServicePortName || - defaultFlowContainer.Ports[i].ContainerPort == variables.DefaultHTTPWorkflowPortIntStr.IntVal { - portIdx = i - break - } - } - if portIdx < 0 { - defaultFlowContainer.Ports = append(defaultFlowContainer.Ports, defaultContainerPort) - } else { - defaultFlowContainer.Ports[portIdx] = defaultContainerPort - } - - return defaultFlowContainer, nil -} - -// ServiceCreator is an objectCreator for a basic Service aiming a vanilla Kubernetes Deployment. -// It maps the default HTTP port (80) to the target Java application webserver on port 8080. -func ServiceCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: corev1.ServiceSpec{ - Selector: lbl, - Ports: []corev1.ServicePort{{ - Name: k8sServicePortName, - Protocol: corev1.ProtocolTCP, - Port: defaultHTTPServicePort, - TargetPort: variables.DefaultHTTPWorkflowPortIntStr, - }}, - }, - } - - return service, nil -} - -// SinkBindingCreator is an ObjectsCreator for SinkBinding. -// It will create v1.SinkBinding based on events defined in workflow. -func SinkBindingCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - - sink, err := knative.GetWorkflowSink(workflow, plf) - if err != nil { - return nil, err - } - if sink == nil { - return nil, nil /*nothing to do*/ - } - - apiVersion := deploymentAPIVersion - kind := deploymentKind - if workflow.Spec.PodTemplate.DeploymentModel == operatorapi.KnativeDeploymentModel { - apiVersion = knativeServingAPIVersion // use knative serving API Version - kind = knativeServiceKind - } - - // subject must be deployment to inject K_SINK, service won't work - sinkBinding := &sourcesv1.SinkBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: strings.ToLower(fmt.Sprintf("%s-sb", workflow.Name)), - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: sourcesv1.SinkBindingSpec{ - SourceSpec: duckv1.SourceSpec{ - Sink: *sink, - }, - BindingSpec: duckv1.BindingSpec{ - Subject: tracker.Reference{ - Name: workflow.Name, - Namespace: workflow.Namespace, - APIVersion: apiVersion, - Kind: kind, - }, - }, - }, - } - return sinkBinding, nil -} - -func getBrokerRefFromPlatform(plf *operatorapi.SonataFlowPlatform, checkRemote bool) (*duckv1.KReference, error) { - // check the local platform - if plf.Spec.Eventing != nil && plf.Spec.Eventing.Broker != nil && plf.Spec.Eventing.Broker.Ref != nil { - ref := plf.Spec.Eventing.Broker.Ref.DeepCopy() - if len(ref.Namespace) == 0 { - ref.Namespace = plf.Namespace // default to the platform namespace - } - return ref, nil - } - // Check the cluster platform - if checkRemote && plf.Status.ClusterPlatformRef != nil && len(plf.Status.ClusterPlatformRef.PlatformRef.Name) > 0 { - platform := &operatorapi.SonataFlowPlatform{} - if err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Namespace: plf.Status.ClusterPlatformRef.PlatformRef.Namespace, Name: plf.Status.ClusterPlatformRef.PlatformRef.Name}, platform); err != nil { - if errors.IsNotFound(err) { - return nil, nil - } - return nil, err - } - return getBrokerRefFromPlatform(platform, false) - } - return nil, nil -} - -func getBrokerRefForEventType(eventType string, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (*duckv1.KReference, error) { - // Check the workflow - for _, source := range workflow.Spec.Sources { - if source.EventType == eventType { - ref := source.Ref.DeepCopy() - if len(ref.Namespace) == 0 { - ref.Namespace = workflow.Namespace // default to the workflow namespace - } - return ref, nil - } - } - // get the broker from the local platform or cluster platform - return getBrokerRefFromPlatform(plf, true) -} - -// TriggersCreator is an ObjectsCreator for Triggers. -// It will create a list of eventingv1.Trigger based on events defined in workflow. -func TriggersCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) ([]client.Object, error) { - var resultObjects []client.Object - lbl := workflowproj.GetMergedLabels(workflow) - - apiVersion := k8sServiceAPIVersion - kind := k8sServiceKind - if workflow.Spec.PodTemplate.DeploymentModel == operatorapi.KnativeDeploymentModel { - apiVersion = knativeServingAPIVersion // use knative serving API Version - kind = knativeServiceKind - } - //consumed - events := workflow.Spec.Flow.Events - for _, event := range events { - // filter out produce events - if event.Kind == cncfmodel.EventKindProduced { - continue - } - brokerRef, err := getBrokerRefForEventType(event.Type, workflow, plf) - if err != nil { - return nil, err - } - if brokerRef == nil || !knative.IsKnativeBroker(brokerRef) { - // No broker configured for the eventType. Skip and will not create trigger for it. - continue - } - if _, err := knative.ValidateBroker(brokerRef.Name, brokerRef.Namespace); err != nil { - return nil, err - } - // construct eventingv1.Trigger - // The trigger must be created in the same namespace as the broker - trigger := &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: kmeta.ChildName(strings.ToLower(fmt.Sprintf("%s-%s-", workflow.Name, event.Name)), string(workflow.GetUID())), - Namespace: brokerRef.Namespace, - Labels: lbl, - }, - Spec: eventingv1.TriggerSpec{ - Broker: brokerRef.Name, - Filter: &eventingv1.TriggerFilter{ - Attributes: eventingv1.TriggerFilterAttributes{ - "type": event.Type, - }, - }, - Subscriber: duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: workflow.Name, - Namespace: workflow.Namespace, - APIVersion: apiVersion, - Kind: kind, - }, - }, - }, - } - resultObjects = append(resultObjects, trigger) - } - return resultObjects, nil -} - -// OpenShiftRouteCreator is an ObjectCreator for a basic Route for a workflow running on OpenShift. -// It enables the exposition of the service using an OpenShift Route. -// See: https://github.com/openshift/api/blob/d170fcdc0fa638b664e4f35f2daf753cb4afe36b/route/v1/route.crd.yaml -func OpenShiftRouteCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - route, err := openshift.RouteForWorkflow(workflow) - return route, err -} - -// UserPropsConfigMapCreator creates an empty ConfigMap to hold the user application properties -func UserPropsConfigMapCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - return workflowproj.CreateNewUserPropsConfigMap(workflow), nil -} - -// ManagedPropsConfigMapCreator creates an empty ConfigMap to hold the external application properties -func ManagedPropsConfigMapCreator(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (client.Object, error) { - props, err := properties.ApplicationManagedProperties(workflow, platform) - if err != nil { - return nil, err - } - return workflowproj.CreateNewManagedPropsConfigMap(workflow, props), nil -} - -// ServiceMonitorCreator is an ObjectsCreator for Service Monitor for the workflow service. -func ServiceMonitorCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - spec := &prometheus.ServiceMonitorSpec{ - Selector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - workflowproj.LabelWorkflow: workflow.Name, - workflowproj.LabelWorkflowNamespace: workflow.Namespace, - }, - }, - Endpoints: []prometheus.Endpoint{ - { - Port: k8sServicePortName, - Path: metricsServicePortPath, - }, - }, - } - serviceMonitor := &prometheus.ServiceMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: *spec, - } - return serviceMonitor, nil -} - -// PodDisruptionBudgetCreator creates a PodDisruptionBudget for workflow. -func PodDisruptionBudgetCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - lbl := workflowproj.GetMergedLabels(workflow) - podDisruptionBudget := &policyv1.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: lbl, - }, - Spec: policyv1.PodDisruptionBudgetSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: workflowproj.GetSelectorLabels(workflow), - }, - }, - } - kubeutil.ApplyPodDisruptionBudgetSpec(podDisruptionBudget, workflow.Spec.PodTemplate.PodDisruptionBudget) - return podDisruptionBudget, nil -} diff --git a/internal/controller/profiles/common/object_creators_test.go b/internal/controller/profiles/common/object_creators_test.go deleted file mode 100644 index 47cea7d8..00000000 --- a/internal/controller/profiles/common/object_creators_test.go +++ /dev/null @@ -1,986 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "testing" - - "github.com/kubesmarts/logic-operator/api/version" - - "github.com/magiconair/properties" - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - "github.com/stretchr/testify/assert" - 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" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - "knative.dev/pkg/kmeta" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - - "github.com/kubesmarts/logic-operator/utils" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -const platformName = "test-platform" - -func Test_ensureWorkflowPropertiesConfigMapMutator(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - platform := test.GetBasePlatformInReadyPhase(workflow.Namespace) - // can't be new - managedProps, _ := ManagedPropsConfigMapCreator(workflow, platform) - managedProps.SetUID("1") - managedProps.SetResourceVersion("1") - managedPropsCM := managedProps.(*corev1.ConfigMap) - - userProps, _ := UserPropsConfigMapCreator(workflow) - userPropsCM := userProps.(*corev1.ConfigMap) - visitor := ManagedPropertiesMutateVisitor(context.TODO(), nil, workflow, platform, userPropsCM) - mutateFn := visitor(managedProps) - - assert.NoError(t, mutateFn()) - assert.Empty(t, managedPropsCM.Data[workflowproj.ApplicationPropertiesFileName]) - assert.NotEmpty(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)]) - - props := properties.MustLoadString(managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)]) - assert.Equal(t, "8080", props.GetString("quarkus.http.port", "")) - - // we change the properties to something different, we add ours and change the default - userPropsCM.Data[workflowproj.ApplicationPropertiesFileName] = "quarkus.http.port=9090\nmy.new.prop=1" - visitor(managedPropsCM) - assert.NoError(t, mutateFn()) - - // we should preserve the default, and still got ours - props = properties.MustLoadString(managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)]) - assert.Equal(t, "8080", props.GetString("quarkus.http.port", "")) - assert.Equal(t, "0.0.0.0", props.GetString("quarkus.http.host", "")) - assert.NotContains(t, "my.new.prop", props.Keys()) -} - -func Test_ensureWorkflowPropertiesConfigMapMutator_DollarReplacement(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - platform := test.GetBasePlatformInReadyPhase(workflow.Namespace) - - managedProps, _ := ManagedPropsConfigMapCreator(workflow, platform) - managedProps.SetName(workflow.Name) - managedProps.SetNamespace(workflow.Namespace) - managedProps.SetUID("0000-0001-0002-0003") - managedPropsCM := managedProps.(*corev1.ConfigMap) - - userProps, _ := UserPropsConfigMapCreator(workflow) - userPropsCM := userProps.(*corev1.ConfigMap) - userPropsCM.Data[workflowproj.ApplicationPropertiesFileName] = "mp.messaging.outgoing.kogito_outgoing_stream.url=${kubernetes:services.v1/event-listener}" - - mutateVisitorFn := ManagedPropertiesMutateVisitor(context.TODO(), nil, workflow, platform, userPropsCM) - - err := mutateVisitorFn(managedPropsCM)() - assert.NoError(t, err) - assert.NotContains(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)], "mp.messaging.outgoing.kogito_outgoing_stream.url") -} - -func TestMergePodSpec(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec.PodTemplate = v1alpha08.FlowPodTemplateSpec{ - Container: v1alpha08.ContainerSpec{ - // this one we can override - Image: test.CommonImageTag, - Ports: []corev1.ContainerPort{ - // let's override a immutable attribute - {Name: utils.DefaultServicePortName, ContainerPort: 9090}, - }, - Env: []corev1.EnvVar{ - // We should be able to override this too - {Name: "ENV1", Value: "VALUE_CUSTOM"}, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "myvolume", ReadOnly: true, MountPath: "/tmp/any/path"}, - }, - }, - PodSpec: v1alpha08.PodSpec{ - ServiceAccountName: "superuser", - Containers: []corev1.Container{ - { - Name: "sidecar", - }, - }, - Volumes: []corev1.Volume{ - { - Name: "myvolume", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: "customproperties"}, - }, - }, - }, - }, - }, - } - - object, err := DeploymentCreator(workflow, nil) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - - assert.Len(t, deployment.Spec.Template.Spec.Containers, 2) - assert.Equal(t, "superuser", deployment.Spec.Template.Spec.ServiceAccountName) - assert.Len(t, deployment.Spec.Template.Spec.Volumes, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Equal(t, test.CommonImageTag, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Equal(t, "VALUE_CUSTOM", flowContainer.Env[0].Value) - assert.Len(t, flowContainer.VolumeMounts, 1) -} - -func TestMergePodSpecOverrideContainers(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec.PodTemplate = v1alpha08.FlowPodTemplateSpec{ - PodSpec: v1alpha08.PodSpec{ - // Try to override the workflow container via the podspec - Containers: []corev1.Container{ - { - Name: v1alpha08.DefaultContainerName, - Image: test.CommonImageTag, - Ports: []corev1.ContainerPort{ - {Name: utils.DefaultServicePortName, ContainerPort: 9090}, - }, - Env: []corev1.EnvVar{ - {Name: "ENV1", Value: "VALUE_CUSTOM"}, - }, - }, - }, - }, - } - - object, err := DeploymentCreator(workflow, nil) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.NotEqual(t, test.CommonImageTag, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Empty(t, flowContainer.Env) -} - -func TestEnsureWorkflowSinkBindingWithWorkflowSinkIsCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - plf := test.GetBasePlatform() - //On Kubernetes we want the service exposed in Dev with NodePort - sinkBinding, err := SinkBindingCreator(workflow, plf) - assert.NoError(t, err) - assert.NotNil(t, sinkBinding) - sinkBinding.SetUID("1") - sinkBinding.SetResourceVersion("1") - - reflectSinkBinding := sinkBinding.(*sourcesv1.SinkBinding) - - assert.NotNil(t, reflectSinkBinding) - assert.NotNil(t, reflectSinkBinding.Spec) - assert.NotEmpty(t, reflectSinkBinding.Spec.Sink) - assert.Equal(t, reflectSinkBinding.Spec.Sink.Ref.Kind, "Broker") - assert.Equal(t, reflectSinkBinding.Spec.Sink.Ref.Name, "default") - assert.NotNil(t, reflectSinkBinding.GetLabels()) - assert.Equal(t, reflectSinkBinding.ObjectMeta.Labels, map[string]string{ - "app": "vet", - "sonataflow.org/workflow-app": "vet", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) -} - -func TestEnsureWorkflowSinkBindingWithPlatformBrokerIsCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - workflow.Spec.Sink = nil - workflow.Spec.Sources = nil - plf := test.GetBasePlatformWithBroker() - sinkBinding, err := SinkBindingCreator(workflow, plf) - assert.NoError(t, err) - assert.NotNil(t, sinkBinding) - sinkBinding.SetUID("1") - sinkBinding.SetResourceVersion("1") - - reflectSinkBinding := sinkBinding.(*sourcesv1.SinkBinding) - - assert.NotNil(t, reflectSinkBinding) - assert.NotNil(t, reflectSinkBinding.Spec) - assert.NotEmpty(t, reflectSinkBinding.Spec.Sink) - assert.Equal(t, reflectSinkBinding.Spec.Sink.Ref.Kind, "Broker") - assert.Equal(t, reflectSinkBinding.Spec.Sink.Ref.Name, "default") - assert.NotNil(t, reflectSinkBinding.GetLabels()) - assert.Equal(t, reflectSinkBinding.ObjectMeta.Labels, map[string]string{"app": "vet", - "sonataflow.org/workflow-app": "vet", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) -} - -func TestEnsureWorkflowSinkBindingWithoutBrokerAreNotCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - workflow.Spec.Sink = nil - workflow.Spec.Sources = nil - plf := test.GetBasePlatformWithBroker() - plf.Spec.Eventing = nil // No broker configured in the platform, but data index and jobs service are enabled - sinkBinding, err := SinkBindingCreator(workflow, plf) - assert.NoError(t, err) - assert.Nil(t, sinkBinding) -} - -func getTrigger(name string, objs []client.Object) *eventingv1.Trigger { - for _, obj := range objs { - if trigger, ok := obj.(*eventingv1.Trigger); ok { - if trigger.Name == name { - return trigger - } - } - } - return nil -} - -func TestEnsureWorkflowTriggersWithPlatformBrokerAreCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - workflow.Spec.Sink = nil - workflow.Spec.Sources = nil - plf := test.GetBasePlatformWithBroker() - plf.Namespace = "platform-namespace" - plf.Spec.Eventing.Broker.Ref.Namespace = plf.Namespace - broker := test.GetDefaultBroker(plf.Namespace) - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, broker).WithStatusSubresource(workflow, broker).Build() - utils.SetClient(cl) - - triggers, err := TriggersCreator(workflow, plf) - assert.NoError(t, err) - assert.NotEmpty(t, triggers) - assert.Len(t, triggers, 2) - //Check the 1st trigger - name := kmeta.ChildName("vet-vetappointmentrequestreceived-", string(workflow.GetUID())) - trigger := getTrigger(name, triggers) - assert.NotNil(t, trigger) - assert.NotNil(t, trigger.GetLabels()) - assert.Equal(t, trigger.GetLabels(), map[string]string{"app": "vet", - "sonataflow.org/workflow-app": "vet", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) - assert.Equal(t, trigger.Namespace, plf.Namespace) //trigger should be in the platform namespace - assert.Equal(t, trigger.Spec.Broker, "default") - assert.NotNil(t, trigger.Spec.Filter) - assert.Len(t, trigger.Spec.Filter.Attributes, 1) - assert.Equal(t, trigger.Spec.Filter.Attributes["type"], "events.vet.appointments.request") - //Check the 2nd trigger - name = kmeta.ChildName("vet-vetappointmentinfo-", string(workflow.GetUID())) - trigger = getTrigger(name, triggers) - assert.NotNil(t, trigger) - assert.NotNil(t, trigger.GetLabels()) - assert.Equal(t, trigger.GetLabels(), map[string]string{"app": "vet", - "sonataflow.org/workflow-app": "vet", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) - assert.Equal(t, trigger.Namespace, plf.Namespace) //trigger should be in the platform namespace - assert.Equal(t, trigger.Spec.Broker, "default") - assert.NotNil(t, trigger.Spec.Filter) - assert.Len(t, trigger.Spec.Filter.Attributes, 1) - assert.Equal(t, trigger.Spec.Filter.Attributes["type"], "events.vet.appointments") -} - -func TestEnsureWorkflowTriggersWithWorkflowBrokerAreCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - workflow.Spec.Sources[0].Destination.Ref.Namespace = workflow.Namespace - workflow.Spec.Sources[1].Destination.Ref.Namespace = workflow.Namespace - plf := test.GetBasePlatform() // No broker defined in the platform - broker1 := test.GetDefaultBroker(workflow.Namespace) - broker1.Name = "broker-appointments-request" - broker2 := test.GetDefaultBroker(workflow.Namespace) - broker2.Name = "broker-appointments" - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, plf, broker1, broker2).WithStatusSubresource(workflow, plf, broker1, broker2).Build() - utils.SetClient(cl) - - triggers, err := TriggersCreator(workflow, plf) - assert.NoError(t, err) - assert.NotEmpty(t, triggers) - assert.Len(t, triggers, 2) - //Check the 1st trigger - name := kmeta.ChildName("vet-vetappointmentrequestreceived-", string(workflow.GetUID())) - - trigger := getTrigger(name, triggers) - assert.NotNil(t, trigger) - assert.NotNil(t, trigger.GetLabels()) - assert.Equal(t, trigger.GetLabels(), map[string]string{"app": "vet", - "sonataflow.org/workflow-app": "vet", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) - assert.Equal(t, trigger.Namespace, workflow.Namespace) //trigger should be in the workflow namespace - assert.Equal(t, trigger.Spec.Broker, "broker-appointments-request") - assert.NotNil(t, trigger.Spec.Filter) - assert.Len(t, trigger.Spec.Filter.Attributes, 1) - assert.Equal(t, trigger.Spec.Filter.Attributes["type"], "events.vet.appointments.request") - //Check the 2nd trigger - name = kmeta.ChildName("vet-vetappointmentinfo-", string(workflow.GetUID())) - trigger = getTrigger(name, triggers) - assert.NotNil(t, trigger) - assert.NotNil(t, trigger.GetLabels()) - assert.Equal(t, trigger.GetLabels(), map[string]string{"app": "vet", - "sonataflow.org/workflow-app": "vet", - "app.kubernetes.io/instance": "vet", - "app.kubernetes.io/version": version.GetImageTagVersion(), - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "vet", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) - assert.Equal(t, trigger.Namespace, workflow.Namespace) //trigger should be in the workflow namespace - assert.Equal(t, trigger.Spec.Broker, "broker-appointments") - assert.NotNil(t, trigger.Spec.Filter) - assert.Len(t, trigger.Spec.Filter.Attributes, 1) - assert.Equal(t, trigger.Spec.Filter.Attributes["type"], "events.vet.appointments") -} - -func TestEnsureWorkflowTriggersWithoutBrokerAreNotCreated(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - workflow.Spec.Sink = nil - workflow.Spec.Sources = nil - plf := test.GetBasePlatform() - - triggers, err := TriggersCreator(workflow, plf) - assert.NoError(t, err) - assert.Nil(t, triggers) -} - -func TestMergePodSpec_WithPostgreSQL_and_JDBC_URL_field(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec = v1alpha08.SonataFlowSpec{ - PodTemplate: v1alpha08.FlowPodTemplateSpec{ - Container: v1alpha08.ContainerSpec{ - // this one we can override - Image: test.CommonImageTag, - Ports: []corev1.ContainerPort{ - // let's override a immutable attribute - {Name: utils.DefaultServicePortName, ContainerPort: 9090}, - }, - Env: []corev1.EnvVar{ - // We should be able to override this too - {Name: "ENV1", Value: "VALUE_CUSTOM"}, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "myvolume", ReadOnly: true, MountPath: "/tmp/any/path"}, - }, - }, - PodSpec: v1alpha08.PodSpec{ - ServiceAccountName: "superuser", - Containers: []corev1.Container{ - { - Name: "sidecar", - }, - }, - Volumes: []corev1.Volume{ - { - Name: "myvolume", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: "customproperties"}, - }, - }, - }, - }, - }, - }, - Persistence: &v1alpha08.PersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - JdbcUrl: "jdbc:postgresql://host:port/database?currentSchema=workflow", - }, - }, - } - - object, err := DeploymentCreator(workflow, nil) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - expectedEnvVars := []corev1.EnvVar{ - { - Name: "ENV1", - Value: "VALUE_CUSTOM", - }, - { - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_USER", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_PASSWORD", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: "postgresql", - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://host:port/database?currentSchema=workflow", - }, - { - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }, - } - assert.Len(t, deployment.Spec.Template.Spec.Containers, 2) - assert.Equal(t, "superuser", deployment.Spec.Template.Spec.ServiceAccountName) - assert.Len(t, deployment.Spec.Template.Spec.Volumes, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Equal(t, test.CommonImageTag, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Equal(t, expectedEnvVars, flowContainer.Env) - assert.Len(t, flowContainer.VolumeMounts, 1) -} - -var ( - postgreSQLPort = 5432 -) - -func TestMergePodSpec_OverrideContainers_WithPostgreSQL_In_Workflow_CR(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec = v1alpha08.SonataFlowSpec{ - PodTemplate: v1alpha08.FlowPodTemplateSpec{ - PodSpec: v1alpha08.PodSpec{ - // Try to override the workflow container via the podspec - Containers: []corev1.Container{ - { - Name: v1alpha08.DefaultContainerName, - Image: test.CommonImageTag, - Ports: []corev1.ContainerPort{ - {Name: utils.DefaultServicePortName, ContainerPort: 9090}, - }, - Env: []corev1.EnvVar{ - {Name: "ENV1", Value: "VALUE_CUSTOM"}, - }, - }, - }, - }, - }, - Persistence: &v1alpha08.PersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - ServiceRef: &v1alpha08.PostgreSQLServiceOptions{ - SQLServiceOptions: &v1alpha08.SQLServiceOptions{ - Name: "test", - Namespace: "foo", - Port: &postgreSQLPort, - DatabaseName: "petstore"}, - DatabaseSchema: "bar"}, - }, - }, - } - - object, err := DeploymentCreator(workflow, nil) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - expectedEnvVars := []corev1.EnvVar{ - { - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_USER", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_PASSWORD", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: "postgresql", - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://test.foo:5432/petstore?currentSchema=bar", - }, - { - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }, - } - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Empty(t, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Equal(t, expectedEnvVars, flowContainer.Env) -} - -func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_CR_And_Worflow_Requesting_It(t *testing.T) { - p := &v1alpha08.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{ - Name: "foo_secret", - UserKey: "username", - PasswordKey: "password", - }, - ServiceRef: &v1alpha08.SQLServiceOptions{ - Name: "service_name", - Namespace: "service_namespace", - Port: &postgreSQLPort, - DatabaseName: "foo", - }, - }, - }, - }, - } - - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec = v1alpha08.SonataFlowSpec{ - Persistence: nil, - } - object, err := DeploymentCreator(workflow, p) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - expectedEnvVars := []corev1.EnvVar{ - { - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "foo_secret"}, Key: "username", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "foo_secret"}, Key: "password", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: "postgresql", - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://service_name.service_namespace:5432/foo?currentSchema=greeting", - }, - { - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }, - } - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Empty(t, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Equal(t, expectedEnvVars, flowContainer.Env) -} - -func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_And_In_Workflow_CR(t *testing.T) { - - p := &v1alpha08.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{ - Name: "foo_secret", - UserKey: "username", - PasswordKey: "password", - }, - ServiceRef: &v1alpha08.SQLServiceOptions{ - Name: "service_name", - Namespace: "service_namespace", - Port: &postgreSQLPort, - DatabaseName: "foo", - }, - }, - }, - }, - } - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec = v1alpha08.SonataFlowSpec{ - PodTemplate: v1alpha08.FlowPodTemplateSpec{ - PodSpec: v1alpha08.PodSpec{ - // Try to override the workflow container via the podspec - Containers: []corev1.Container{ - { - Name: v1alpha08.DefaultContainerName, - Image: test.CommonImageTag, - Ports: []corev1.ContainerPort{ - {Name: utils.DefaultServicePortName, ContainerPort: 9090}, - }, - Env: []corev1.EnvVar{ - {Name: "ENV1", Value: "VALUE_CUSTOM"}, - }, - }, - }, - }, - }, - Persistence: &v1alpha08.PersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - ServiceRef: &v1alpha08.PostgreSQLServiceOptions{ - SQLServiceOptions: &v1alpha08.SQLServiceOptions{ - Name: "test", - Namespace: "default", - Port: &postgreSQLPort, - DatabaseName: "my_database"}, - DatabaseSchema: "bar"}, - }, - }, - } - object, err := DeploymentCreator(workflow, p) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - expectedEnvVars := []corev1.EnvVar{ - { - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_USER", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "test"}, Key: "POSTGRESQL_PASSWORD", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: "postgresql", - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://test.default:5432/my_database?currentSchema=bar", - }, - { - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }, - } - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Empty(t, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Equal(t, expectedEnvVars, flowContainer.Env) -} - -func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_But_Workflow_CR_Not_Requesting_it(t *testing.T) { - p := &v1alpha08.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{ - Name: "foo_secret", - UserKey: "username", - PasswordKey: "password", - }, - ServiceRef: &v1alpha08.SQLServiceOptions{ - Name: "service_name", - Namespace: "service_namespace", - Port: &postgreSQLPort, - DatabaseName: "foo", - }, - }, - }, - }, - } - workflow := test.GetBaseSonataFlow(t.Name()) - workflow.Spec = v1alpha08.SonataFlowSpec{ - Persistence: &v1alpha08.PersistenceOptionsSpec{}, - } - object, err := DeploymentCreator(workflow, p) - assert.NoError(t, err) - - deployment := object.(*appsv1.Deployment) - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - flowContainer, _ := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) - assert.Empty(t, flowContainer.Image) - assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) - assert.Nil(t, flowContainer.Env) -} - -func TestDefaultContainer_WithPlatformPersistenceWorkflowWithDefaultProfile(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - doTestDefaultContainer_WithPlatformPersistence(t, workflow, true) -} - -func TestDefaultContainer_WithPlatformPersistenceWorkflowWithPreviewProfile(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflowproj.SetWorkflowProfile(workflow, metadata.PreviewProfile) - doTestDefaultContainer_WithPlatformPersistence(t, workflow, true) -} - -func TestDefaultContainer_WithPlatformPersistenceWorkflowWithGitOpsProfile(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflowproj.SetWorkflowProfile(workflow, metadata.GitOpsProfile) - doTestDefaultContainer_WithPlatformPersistence(t, workflow, true) -} - -func TestDefaultContainer_WithPlatformPersistenceWorkflowWithDevProfile(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflowproj.SetWorkflowProfile(workflow, metadata.DevProfile) - doTestDefaultContainer_WithPlatformPersistence(t, workflow, false) -} - -func doTestDefaultContainer_WithPlatformPersistence(t *testing.T, workflow *v1alpha08.SonataFlow, checkPersistence bool) { - platform := &v1alpha08.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{ - Name: "foo_secret", - UserKey: "username", - PasswordKey: "password", - }, - ServiceRef: &v1alpha08.SQLServiceOptions{ - Name: "service_name", - Namespace: "service_namespace", - Port: &postgreSQLPort, - DatabaseName: "foo", - }, - }, - }, - }, - } - - container, err := defaultContainer(workflow, platform) - assert.Nil(t, err) - assert.NotNil(t, container) - assert.Equal(t, "workflow", container.Name) - - //verify default container port. - assert.Equal(t, 1, len(container.Ports)) - assert.Equal(t, "h2c", container.Ports[0].Name) - assert.Equal(t, int32(0), container.Ports[0].HostPort) - assert.Equal(t, int32(8080), container.Ports[0].ContainerPort) - assert.Equal(t, corev1.Protocol("TCP"), container.Ports[0].Protocol) - assert.Equal(t, "", container.Ports[0].HostIP) - - //verify default container health checks - assert.Equal(t, &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - Exec: nil, - HTTPGet: &corev1.HTTPGetAction{ - Path: "/q/health/live", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 8080, - StrVal: "", - }, - Host: "", - Scheme: "", - HTTPHeaders: nil, - }, - TCPSocket: nil, - GRPC: nil, - }, - InitialDelaySeconds: 0, - TimeoutSeconds: 3, - PeriodSeconds: 15, - SuccessThreshold: 0, - FailureThreshold: 0, - TerminationGracePeriodSeconds: nil, - }, container.LivenessProbe) - - assert.Equal(t, &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - Exec: nil, - HTTPGet: &corev1.HTTPGetAction{ - Path: "/q/health/ready", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 8080, - StrVal: "", - }, - Host: "", - Scheme: "", - HTTPHeaders: nil, - }, - TCPSocket: nil, - GRPC: nil, - }, - InitialDelaySeconds: 0, - TimeoutSeconds: 3, - PeriodSeconds: 15, - SuccessThreshold: 0, - FailureThreshold: 0, - TerminationGracePeriodSeconds: nil, - }, container.ReadinessProbe) - - assert.Equal(t, &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - Exec: nil, - HTTPGet: &corev1.HTTPGetAction{ - Path: "/q/health/started", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 8080, - StrVal: "", - }, - Host: "", - Scheme: "", - HTTPHeaders: nil, - }, - TCPSocket: nil, - GRPC: nil, - }, - InitialDelaySeconds: 10, - TimeoutSeconds: 3, - PeriodSeconds: 15, - SuccessThreshold: 0, - FailureThreshold: 5, - TerminationGracePeriodSeconds: nil, - }, container.StartupProbe) - - //verify the persistence configuration is present if requested. - if checkPersistence { - expectedEnvVars := []corev1.EnvVar{ - { - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "foo_secret"}, Key: "username", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "foo_secret"}, Key: "password", - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: "postgresql", - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://service_name.service_namespace:5432/foo?currentSchema=greeting", - }, - { - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }, - } - assert.Equal(t, expectedEnvVars, container.Env) - } else { - //no persistence - assert.Nil(t, container.Env) - } -} - -func TestEnsureWorkflowServiceMonitorIsCreatedWhenDeployedAsDeployment(t *testing.T) { - workflow := test.GetVetEventSonataFlow(t.Name()) - assert.Equal(t, workflow.IsKnativeDeployment(), false) - serviceMonitor, err := ServiceMonitorCreator(workflow) - assert.NoError(t, err) - assert.NotNil(t, serviceMonitor) - serviceMonitor.SetUID("1") - serviceMonitor.SetResourceVersion("1") - reflectServiceMonitor := serviceMonitor.(*prometheus.ServiceMonitor) - - assert.NotNil(t, reflectServiceMonitor) - assert.NotNil(t, reflectServiceMonitor.Spec) - assert.Equal(t, len(reflectServiceMonitor.Spec.Selector.MatchLabels), 2) - assert.Equal(t, reflectServiceMonitor.Spec.Selector.MatchLabels[workflowproj.LabelWorkflow], workflow.Name) - assert.Equal(t, reflectServiceMonitor.Spec.Selector.MatchLabels[workflowproj.LabelWorkflowNamespace], workflow.Namespace) - assert.Equal(t, reflectServiceMonitor.Spec.Endpoints[0].Port, k8sServicePortName) - assert.Equal(t, reflectServiceMonitor.Spec.Endpoints[0].Path, metricsServicePortPath) - assert.NotNil(t, reflectServiceMonitor.GetLabels()) - assert.Equal(t, reflectServiceMonitor.ObjectMeta.Labels, map[string]string{ - "app": workflow.Name, - "sonataflow.org/workflow-app": workflow.Name, - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": workflow.Name, - "app.kubernetes.io/instance": workflow.Name, - "app.kubernetes.io/version": version.GetImageTagVersion(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator"}) -} diff --git a/internal/controller/profiles/common/persistence/persistence.go b/internal/controller/profiles/common/persistence/persistence.go deleted file mode 100644 index c8be27a1..00000000 --- a/internal/controller/profiles/common/persistence/persistence.go +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 persistence - -import ( - "github.com/magiconair/properties" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const ( - QuarkusFlywayMigrateAtStart string = "quarkus.flyway.migrate-at-start" - QuarkusDatasourceDBKind string = "quarkus.datasource.db-kind" - QuarkusDatasourceJDBCURL string = "quarkus.datasource.jdbc.url" - KogitoPersistenceType string = "kogito.persistence.type" - JDBCPersistenceType string = "jdbc" - KogitoPersistenceQueryTimeoutMillis string = "kogito.persistence.query.timeout.millis" - KogitoPersistenceProtoMarshaller string = "kogito.persistence.proto.marshaller" - PostgreSQLDBKind string = "postgresql" -) - -// ResolveWorkflowPersistenceProperties returns the set of application properties required for the workflow persistence. -// Never nil. -func ResolveWorkflowPersistenceProperties(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (*properties.Properties, error) { - if UsesPostgreSQLPersistence(workflow, platform) { - return GetPostgreSQLWorkflowProperties(workflow), nil - } - return properties.NewProperties(), nil -} diff --git a/internal/controller/profiles/common/persistence/persistence_suite_test.go b/internal/controller/profiles/common/persistence/persistence_suite_test.go deleted file mode 100644 index 087240c5..00000000 --- a/internal/controller/profiles/common/persistence/persistence_suite_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 persistence - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestPersistence(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Persistence Suite") -} diff --git a/internal/controller/profiles/common/persistence/persistence_test.go b/internal/controller/profiles/common/persistence/persistence_test.go deleted file mode 100644 index f2e11da0..00000000 --- a/internal/controller/profiles/common/persistence/persistence_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 persistence - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func TestResolveWorkflowPersistenceProperties_WithWorkflowPersistence(t *testing.T) { - workflow := operatorapi.SonataFlow{ - Spec: operatorapi.SonataFlowSpec{ - Persistence: &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{}, - }, - }, - } - platform := operatorapi.SonataFlowPlatform{} - testResolveWorkflowPersistencePropertiesWithPersistence(t, &workflow, &platform) -} - -func TestResolveWorkflowPersistenceProperties_WithPlatformPersistence(t *testing.T) { - workflow := operatorapi.SonataFlow{} - platform := operatorapi.SonataFlowPlatform{ - Spec: operatorapi.SonataFlowPlatformSpec{ - Persistence: &operatorapi.PlatformPersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PlatformPersistencePostgreSQL{}, - }, - }, - } - testResolveWorkflowPersistencePropertiesWithPersistence(t, &workflow, &platform) -} - -func TestResolveWorkflowPersistenceProperties_WithPlatformPersistenceButBannedInWorkflow(t *testing.T) { - workflow := operatorapi.SonataFlow{} - workflow.Spec.Persistence = &operatorapi.PersistenceOptionsSpec{} - platform := operatorapi.SonataFlowPlatform{ - Spec: operatorapi.SonataFlowPlatformSpec{ - Persistence: &operatorapi.PlatformPersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PlatformPersistencePostgreSQL{}, - }, - }, - } - props, err := ResolveWorkflowPersistenceProperties(&workflow, &platform) - assert.NotNil(t, props) - assert.Nil(t, err) - assert.Equal(t, 0, props.Len()) -} - -func TestResolveWorkflowPersistenceProperties_WithNoPersistence(t *testing.T) { - workflow := operatorapi.SonataFlow{} - platform := operatorapi.SonataFlowPlatform{} - props, err := ResolveWorkflowPersistenceProperties(&workflow, &platform) - assert.NotNil(t, props) - assert.Nil(t, err) - assert.Equal(t, 0, props.Len()) -} - -func testResolveWorkflowPersistencePropertiesWithPersistence(t *testing.T, workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) { - props, err := ResolveWorkflowPersistenceProperties(workflow, platform) - assert.Nil(t, err) - assert.NotNil(t, props) - assert.Equal(t, 3, props.Len()) - value, _ := props.Get("kogito.persistence.type") - assert.Equal(t, "jdbc", value) - value, _ = props.Get("quarkus.datasource.db-kind") - assert.Equal(t, "postgresql", value) - value, _ = props.Get("kogito.persistence.proto.marshaller") - assert.Equal(t, "false", value) -} diff --git a/internal/controller/profiles/common/persistence/postgresql.go b/internal/controller/profiles/common/persistence/postgresql.go deleted file mode 100644 index a43e1118..00000000 --- a/internal/controller/profiles/common/persistence/postgresql.go +++ /dev/null @@ -1,237 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 persistence - -import ( - "fmt" - "strings" - - "github.com/magiconair/properties" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - - corev1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" -) - -const ( - defaultDatabaseName = "sonataflow" -) - -// ConfigurePostgreSQLEnv returns the common env variables required for the DataIndex or JobsService when postresql persistence is used. -func ConfigurePostgreSQLEnv(postgresql *operatorapi.PersistencePostgreSQL, databaseSchema, databaseNamespace string, includeReactiveUrl bool) []corev1.EnvVar { - dataSourcePort := constants.DefaultPostgreSQLPort - databaseName := defaultDatabaseName - dataSourceURL := postgresql.JdbcUrl - if postgresql.ServiceRef != nil { - if len(postgresql.ServiceRef.DatabaseSchema) > 0 { - databaseSchema = postgresql.ServiceRef.DatabaseSchema - } - if len(postgresql.ServiceRef.Namespace) > 0 { - databaseNamespace = postgresql.ServiceRef.Namespace - } - if postgresql.ServiceRef.Port != nil { - dataSourcePort = *postgresql.ServiceRef.Port - } - if len(postgresql.ServiceRef.DatabaseName) > 0 { - databaseName = postgresql.ServiceRef.DatabaseName - } - dataSourceURL = fmt.Sprintf("jdbc:postgresql://%s.%s:%d/%s?currentSchema=%s", postgresql.ServiceRef.Name, databaseNamespace, dataSourcePort, databaseName, databaseSchema) - } - secretRef := corev1.LocalObjectReference{ - Name: postgresql.SecretRef.Name, - } - quarkusDatasourceUsername := "POSTGRESQL_USER" - if len(postgresql.SecretRef.UserKey) > 0 { - quarkusDatasourceUsername = postgresql.SecretRef.UserKey - } - quarkusDatasourcePassword := "POSTGRESQL_PASSWORD" - if len(postgresql.SecretRef.PasswordKey) > 0 { - quarkusDatasourcePassword = postgresql.SecretRef.PasswordKey - } - env := []corev1.EnvVar{ - { - Name: "QUARKUS_DATASOURCE_USERNAME", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: quarkusDatasourceUsername, - LocalObjectReference: secretRef, - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: quarkusDatasourcePassword, - LocalObjectReference: secretRef, - }, - }, - }, - { - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - }, - { - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: dataSourceURL, - }, - } - if includeReactiveUrl { - dataSourceReactiveURL := strings.TrimPrefix(dataSourceURL, "jdbc:") - dataSourceReactiveURL = strings.ReplaceAll(dataSourceReactiveURL, "currentSchema=", "search_path=") - env = append(env, corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_REACTIVE_URL", - Value: dataSourceReactiveURL, - }) - } - env = append(env, corev1.EnvVar{ - Name: "KOGITO_PERSISTENCE_TYPE", - Value: "jdbc", - }) - return env -} - -func ConfigureWorkflowPersistence(serviceContainer *corev1.Container, config *operatorapi.PersistenceOptionsSpec, defaultSchema, namespace string) *corev1.Container { - if config.PostgreSQL == nil { - return serviceContainer - } - c := serviceContainer.DeepCopy() - c.Env = append(c.Env, ConfigurePostgreSQLEnv(config.PostgreSQL, defaultSchema, namespace, false)...) - return c -} - -func RetrieveConfiguration(primary *v1alpha08.PersistenceOptionsSpec, platformPersistence *v1alpha08.PlatformPersistenceOptionsSpec, schema string) *v1alpha08.PersistenceOptionsSpec { - if primary != nil { - return primary - } - if platformPersistence == nil { - return nil - } - return buildPersistenceOptionsSpec(platformPersistence, schema) -} - -// RetrievePostgreSQLConfiguration return the PersistenceOptionsSpec considering that postgresql is the database manager -// to look for. Gives priority to the primary configuration. -func RetrievePostgreSQLConfiguration(primary *v1alpha08.PersistenceOptionsSpec, platformPersistence *v1alpha08.PlatformPersistenceOptionsSpec, schema string) *v1alpha08.PersistenceOptionsSpec { - if primary != nil && primary.PostgreSQL != nil { - return primary - } - return buildPersistenceOptionsSpec(platformPersistence, schema) -} - -func buildPersistenceOptionsSpec(platformPersistence *v1alpha08.PlatformPersistenceOptionsSpec, schema string) *v1alpha08.PersistenceOptionsSpec { - c := &v1alpha08.PersistenceOptionsSpec{} - if platformPersistence.PostgreSQL != nil { - c.PostgreSQL = &v1alpha08.PersistencePostgreSQL{ - SecretRef: platformPersistence.PostgreSQL.SecretRef, - } - if platformPersistence.PostgreSQL.ServiceRef != nil { - c.PostgreSQL.ServiceRef = &v1alpha08.PostgreSQLServiceOptions{ - SQLServiceOptions: platformPersistence.PostgreSQL.ServiceRef, - DatabaseSchema: schema, - } - } else { - c.PostgreSQL.JdbcUrl = platformPersistence.PostgreSQL.JdbcUrl - } - } - return c -} - -func UsesPostgreSQLPersistence(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) bool { - return (workflow.Spec.Persistence != nil && workflow.Spec.Persistence.PostgreSQL != nil) || - (workflow.Spec.Persistence == nil && platform.Spec.Persistence != nil && platform.Spec.Persistence.PostgreSQL != nil) -} - -// GetPostgreSQLExtensions returns the Quarkus extensions required for postgresql persistence. -func GetPostgreSQLExtensions() []cfg.GroupArtifactId { - return cfg.GetCfg().PostgreSQLPersistenceExtensions -} - -// GetPostgreSQLWorkflowProperties returns the set of application properties required for postgresql persistence. -// Never nil. -func GetPostgreSQLWorkflowProperties(workflow *operatorapi.SonataFlow) *properties.Properties { - props := properties.NewProperties() - if !profiles.IsDevProfile(workflow) && !profiles.IsGitOpsProfile(workflow) { - // build-time property required by kogito-runtimes to feed flyway build-time settings and package the necessary .sql files. - props.Set(QuarkusDatasourceDBKind, PostgreSQLDBKind) - // build-time properties for kogito-runtimes to use jdbc - props.Set(KogitoPersistenceType, JDBCPersistenceType) - props.Set(KogitoPersistenceProtoMarshaller, "false") - } - return props -} - -// GetDBSchemaName Parses jdbc url and returns the schema name -func GetDBSchemaName(persistencePostgreSQL *operatorapi.PersistencePostgreSQL, defaultSchemaName string) string { - if persistencePostgreSQL != nil && persistencePostgreSQL.ServiceRef != nil && len(persistencePostgreSQL.ServiceRef.DatabaseSchema) > 0 { - return persistencePostgreSQL.ServiceRef.DatabaseSchema - } - - if persistencePostgreSQL != nil && len(persistencePostgreSQL.JdbcUrl) > 0 { - jdbcURL := persistencePostgreSQL.JdbcUrl - _, a, found := strings.Cut(jdbcURL, "currentSchema=") - - if found { - if strings.Contains(a, "&") { - b, _, found := strings.Cut(a, "&") - if found { - return b - } - } else { - return a - } - } - } - return defaultSchemaName -} - -func MapToPersistencePostgreSQL(platform *operatorapi.SonataFlowPlatform, defaultSchemaName string) *operatorapi.PersistencePostgreSQL { - if platform.Spec.Persistence != nil && platform.Spec.Persistence.PostgreSQL != nil { - persistencePostgreSQL := &operatorapi.PersistencePostgreSQL{} - persistencePostgreSQL.SecretRef = platform.Spec.Persistence.PostgreSQL.SecretRef - - if len(platform.Spec.Persistence.PostgreSQL.JdbcUrl) > 0 { - persistencePostgreSQL.JdbcUrl = platform.Spec.Persistence.PostgreSQL.JdbcUrl - } - - serviceRef := &operatorapi.PostgreSQLServiceOptions{} - if platform.Spec.Persistence.PostgreSQL.ServiceRef != nil { - - serviceRef.DatabaseSchema = defaultSchemaName - serviceRef.SQLServiceOptions = &operatorapi.SQLServiceOptions{} - - if len(platform.Spec.Persistence.PostgreSQL.ServiceRef.Name) > 0 { - serviceRef.SQLServiceOptions.Name = platform.Spec.Persistence.PostgreSQL.ServiceRef.Name - } - - if len(platform.Spec.Persistence.PostgreSQL.ServiceRef.DatabaseName) > 0 { - serviceRef.SQLServiceOptions.DatabaseName = platform.Spec.Persistence.PostgreSQL.ServiceRef.DatabaseName - } - - persistencePostgreSQL.ServiceRef = serviceRef - } - return persistencePostgreSQL - } - - return nil -} diff --git a/internal/controller/profiles/common/persistence/postgresql_test.go b/internal/controller/profiles/common/persistence/postgresql_test.go deleted file mode 100644 index 4930d6c4..00000000 --- a/internal/controller/profiles/common/persistence/postgresql_test.go +++ /dev/null @@ -1,150 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 persistence - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const ( - primaryPostgreSQLJdbc = "jdbc:postgresql://host:port/database?currentSchema=primary-database" - - platformPostgreSQLJdbc = "jdbc:postgresql://host:port/database?currentSchema=platform-database" - schemaName = "my-schema" -) - -var ( - primaryPostgreSQLSecret = operatorapi.PostgreSQLSecretOptions{ - Name: "primary-secret", - } - primaryPostreSQLService = operatorapi.PostgreSQLServiceOptions{ - SQLServiceOptions: &operatorapi.SQLServiceOptions{Name: "primary-service"}, - DatabaseSchema: "primary-schema", - } - plaformPostgreSQLSecret = operatorapi.PostgreSQLSecretOptions{ - Name: "platform-secret", - } - platformPostreSQLService = operatorapi.SQLServiceOptions{ - Name: "platform-service", - } -) - -var _ = Describe("RetrievePostgreSQLConfiguration", func() { - DescribeTable("calculation", - func(primary *operatorapi.PersistenceOptionsSpec, - platformPersistence *operatorapi.PlatformPersistenceOptionsSpec, - schema string, - expectedConfig *operatorapi.PersistenceOptionsSpec) { - result := RetrievePostgreSQLConfiguration(primary, platformPersistence, schema) - Expect(expectedConfig).To(Equal(result)) - }, - Entry("primary is postgresql with JdbcUrl", buildPrimaryIsPostgreSQLWithJdbcUrl(), - buildPlatformIsPostgreSQLWithJdbcUrl(), - schemaName, - buildPrimaryIsPostgreSQLWithJdbcUrl()), - Entry("primary is postgresql ServiceRef", buildPrimaryIsPostgreSQLWithServiceRef(), - buildPlatformIsPostgreSQLWithJdbcUrl(), - schemaName, - buildPrimaryIsPostgreSQLWithServiceRef()), - Entry("primary is nil, platform with JdbcUrl", - nil, - buildPlatformIsPostgreSQLWithJdbcUrl(), - schemaName, - &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - SecretRef: plaformPostgreSQLSecret, - JdbcUrl: platformPostgreSQLJdbc, - }, - }), - Entry("primary is empty, platform with JdbcUrl", - &operatorapi.PersistenceOptionsSpec{}, - buildPlatformIsPostgreSQLWithJdbcUrl(), - schemaName, - &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - SecretRef: plaformPostgreSQLSecret, - JdbcUrl: platformPostgreSQLJdbc, - }, - }), - Entry("primary is nil, platform with ServiceRef", - nil, - buildPlatformIsPostgreSQLWithServiceRef(), - schemaName, - &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - ServiceRef: &operatorapi.PostgreSQLServiceOptions{ - SQLServiceOptions: &platformPostreSQLService, - DatabaseSchema: schemaName, - }, - SecretRef: plaformPostgreSQLSecret, - }, - }), - Entry("primary is empty, platform with ServiceRef", - &operatorapi.PersistenceOptionsSpec{}, - buildPlatformIsPostgreSQLWithServiceRef(), - schemaName, - &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - ServiceRef: &operatorapi.PostgreSQLServiceOptions{ - SQLServiceOptions: &platformPostreSQLService, - DatabaseSchema: schemaName, - }, - SecretRef: plaformPostgreSQLSecret, - }, - }), - ) -}) - -func buildPrimaryIsPostgreSQLWithJdbcUrl() *operatorapi.PersistenceOptionsSpec { - return &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - JdbcUrl: primaryPostgreSQLJdbc, - SecretRef: primaryPostgreSQLSecret, - }, - } -} - -func buildPrimaryIsPostgreSQLWithServiceRef() *operatorapi.PersistenceOptionsSpec { - return &operatorapi.PersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PersistencePostgreSQL{ - ServiceRef: &primaryPostreSQLService, - SecretRef: primaryPostgreSQLSecret, - }, - } -} - -func buildPlatformIsPostgreSQLWithJdbcUrl() *operatorapi.PlatformPersistenceOptionsSpec { - return &operatorapi.PlatformPersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PlatformPersistencePostgreSQL{ - JdbcUrl: platformPostgreSQLJdbc, - SecretRef: plaformPostgreSQLSecret, - }, - } -} - -func buildPlatformIsPostgreSQLWithServiceRef() *operatorapi.PlatformPersistenceOptionsSpec { - return &operatorapi.PlatformPersistenceOptionsSpec{ - PostgreSQL: &operatorapi.PlatformPersistencePostgreSQL{ - ServiceRef: &platformPostreSQLService, - SecretRef: plaformPostgreSQLSecret, - }, - } -} diff --git a/internal/controller/profiles/common/properties/discovery.go b/internal/controller/profiles/common/properties/discovery.go deleted file mode 100644 index 7c57d559..00000000 --- a/internal/controller/profiles/common/properties/discovery.go +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 properties - -import ( - "context" - "fmt" - "regexp" - "strings" - - "github.com/magiconair/properties" - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/log" -) - -const ( - microprofileServiceCatalogPropertyPrefix = "org.kie.kogito.addons.discovery." - discoveryLikePropertyPattern = "^\\${(kubernetes|knative|openshift):(.*)}$" - knativeServiceOperationPrefix = "knative:services.v1.serving.knative.dev" -) - -var discoveryLikePropertyExpr = regexp.MustCompile(discoveryLikePropertyPattern) - -func removeDiscoveryProperties(props *properties.Properties) { - for _, k := range props.Keys() { - if strings.HasPrefix(k, microprofileServiceCatalogPropertyPrefix) { - props.Delete(k) - } - } -} - -func generateMicroprofileServiceCatalogProperty(serviceUri string) string { - escapedServiceUri := escapeValue(serviceUri, ":") - escapedServiceUri = escapeValue(escapedServiceUri, "/") - escapedServiceUri = escapeValue(escapedServiceUri, "=") - property := microprofileServiceCatalogPropertyPrefix + escapedServiceUri - return property -} - -func escapeValue(unescaped string, value string) string { - return strings.Replace(unescaped, value, fmt.Sprintf("\\%s", value), -1) -} - -// generateDiscoveryProperties Given a user configured properties set, generates the MicroProfileConfigServiceCatalog -// required properties to resolve the corresponding service addresses base on these properties. -// e.g. -// Given a user configured property like this: -// -// quarkus.rest-client.acme_financial_service_yml.url=${kubernetes:services.v1/usecase1/financial-service?port=http-port} -// -// generates the following property: -// -// org.kie.kogito.addons.discovery.kubernetes\:services.v1\/usecase1\/financial-service?port\=http-port=http://10.5.9.1:8080 -// -// where http://10.5.9.1:8080 is the corresponding k8s cloud address for the service financial-service in the namespace usecase1. -func generateDiscoveryProperties(ctx context.Context, catalog discovery.ServiceCatalog, props *properties.Properties, - workflow *operatorapi.SonataFlow) *properties.Properties { - klog.V(log.I).Infof("Generating service discovery properties for workflow: %s, and namespace: %s.", workflow.Name, workflow.Namespace) - result := properties.NewProperties() - props.DisableExpansion = true - for _, k := range props.Keys() { - value, _ := props.Get(k) - klog.V(log.I).Infof("Scanning property %s=%s for service discovery configuration.", k, value) - if !discoveryLikePropertyExpr.MatchString(value) { - klog.V(log.I).Infof("Skipping property %s=%s since it does not look like a service discovery configuration.", k, value) - } else { - klog.V(log.I).Infof("Property %s=%s looks like a service discovery configuration.", k, value) - plainUri := value[2 : len(value)-1] - if uri, err := discovery.ParseUri(plainUri); err != nil { - klog.V(log.I).Infof("Property %s=%s not correspond to a valid service discovery configuration, it will be excluded from service discovery.", k, value) - } else { - if len(uri.Namespace) == 0 { - klog.V(log.I).Infof("Current service discovery configuration has no configured namespace, workflow namespace: %s will be used instead.", workflow.Namespace) - uri.Namespace = workflow.Namespace - } - if address, err := catalog.Query(ctx, *uri, discovery.KubernetesDNSAddress); err != nil { - klog.V(log.E).ErrorS(err, "An error was produced during service address resolution.", "serviceUri", plainUri) - } else { - klog.V(log.I).Infof("Service: %s was resolved into the following address: %s.", plainUri, address) - mpProperty := generateMicroprofileServiceCatalogProperty(plainUri) - klog.V(log.I).Infof("Generating microprofile service catalog property %s=%s.", mpProperty, address) - result.MustSet(mpProperty, address) - klog.V(log.I).Infof("Overriding the discoverable value as the managed property %s=%s.", k, address) - result.MustSet(k, address) - } - } - } - } - - for _, function := range workflow.Spec.Flow.Functions { - klog.V(log.I).Infof("Scanning function: %s for service discovery configuration.", function.Name) - if strings.HasPrefix(function.Operation, knativeServiceOperationPrefix) { - klog.V(log.I).Infof("Function %s looks to be a knative service invocation on service: %s.", function.Name, function.Operation) - if uri, err := discovery.ParseUri(function.Operation); err != nil { - klog.V(log.I).Infof("Operation: %s not correspond to a valid service discovery configuration, it will be excluded from service discovery.", function.Operation) - } else { - if len(uri.Namespace) == 0 { - klog.V(log.I).Infof("Current operation has no configured namespace, workflow namespace: %s will be used instead.", workflow.Namespace) - uri.Namespace = workflow.Namespace - } - if address, err := catalog.Query(ctx, *uri, ""); err != nil { - klog.V(log.E).ErrorS(err, "An error was produced during service address resolution.", "serviceUri", function.Operation) - } else { - // when the knative service is invoked from the workflow as an Operation, the query params are not - // used for the microprofile property generation. - trimmedUri := function.Operation - if questionMarkIndex := strings.Index(trimmedUri, "?"); questionMarkIndex > 0 { - trimmedUri = function.Operation[:questionMarkIndex] - } - klog.V(log.I).Infof("Service: %s was resolved into the following address: %s.", function.Operation, address) - mpProperty := generateMicroprofileServiceCatalogProperty(trimmedUri) - klog.V(log.I).Infof("Generating microprofile service catalog property %s=%s.", mpProperty, address) - result.MustSet(mpProperty, address) - } - } - } - } - return result -} diff --git a/internal/controller/profiles/common/properties/discovery_test.go b/internal/controller/profiles/common/properties/discovery_test.go deleted file mode 100644 index 9dbec410..00000000 --- a/internal/controller/profiles/common/properties/discovery_test.go +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 properties - -import ( - "context" - "testing" - - "github.com/magiconair/properties" - "github.com/serverlessworkflow/sdk-go/v2/model" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func Test_generateDiscoveryProperties(t *testing.T) { - - catalogService := &mockCatalogService{} - - propertiesContent := "property1=value1\n" - propertiesContent = propertiesContent + "property2=${value2}\n" - propertiesContent = propertiesContent + "service1=${kubernetes:services.v1/namespace1/my-service1}\n" - propertiesContent = propertiesContent + "service2=${kubernetes:services.v1/my-service2}\n" - propertiesContent = propertiesContent + "service3=${kubernetes:services.v1/my-service3?port=http-port}\n" - - propertiesContent = propertiesContent + "non_service4=${kubernetes:--kaka}" - - workflow := v1alpha08.Flow{ - Functions: []model.Function{ - { - Name: "knServiceInvocation1", - Operation: "knative:services.v1.serving.knative.dev/namespace1/my-kn-service1?path=/knative-function1", - }, - { - Name: "knServiceInvocation2", - Operation: "knative:services.v1.serving.knative.dev/my-kn-service3?path=/knative-function3", - }, - }, - } - - props := properties.MustLoadString(propertiesContent) - result := generateDiscoveryProperties(context.TODO(), catalogService, props, &operatorapi.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{Name: "helloworld", Namespace: defaultNamespace}, - Spec: v1alpha08.SonataFlowSpec{Flow: workflow}, - }) - - assert.Equal(t, 8, result.Len()) - assertHasProperty(t, result, "service1", myService1Address) - assertHasProperty(t, result, "service2", myService2Address) - assertHasProperty(t, result, "service3", myService3Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/namespace1\\/my-service1", myService1Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/namespace1\\/my-service1", myService1Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/namespace1\\/my-service1", myService1Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/my-service2", myService2Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/my-service3?port\\=http-port", myService3Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.knative\\:services.v1.serving.knative.dev\\/namespace1\\/my-kn-service1", myKnService1Address) - assertHasProperty(t, result, "org.kie.kogito.addons.discovery.knative\\:services.v1.serving.knative.dev\\/my-kn-service3", myKnService3Address) -} - -func Test_generateMicroprofileServiceCatalogProperty(t *testing.T) { - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:services.v1/namespace1/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/namespace1\\/financial-service") - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:services.v1/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:services.v1\\/financial-service") - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:pods.v1/namespace1/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:pods.v1\\/namespace1\\/financial-service") - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:pods.v1/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:pods.v1\\/financial-service") - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:deployments.v1.apps/namespace1/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:deployments.v1.apps\\/namespace1\\/financial-service") - - doTestGenerateMicroprofileServiceCatalogProperty(t, "kubernetes:deployments.v1.apps/financial-service", - "org.kie.kogito.addons.discovery.kubernetes\\:deployments.v1.apps\\/financial-service") -} - -func doTestGenerateMicroprofileServiceCatalogProperty(t *testing.T, serviceUri string, expectedProperty string) { - mpProperty := generateMicroprofileServiceCatalogProperty(serviceUri) - assert.Equal(t, mpProperty, expectedProperty, "expected microprofile service catalog property for serviceUri: %s, is %s, but the returned value was: %s", serviceUri, expectedProperty, mpProperty) -} diff --git a/internal/controller/profiles/common/properties/knative.go b/internal/controller/profiles/common/properties/knative.go deleted file mode 100644 index 955de142..00000000 --- a/internal/controller/profiles/common/properties/knative.go +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 properties - -import ( - "github.com/magiconair/properties" - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" -) - -// generateKnativeEventingWorkflowProperties returns the set of application properties required for the workflow to produce or consume -// Knative Events. -// Never nil. -func generateKnativeEventingWorkflowProperties(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (*properties.Properties, error) { - props := properties.NewProperties() - props.Set(constants.KnativeHealthEnabled, "false") - sink, err := knative.GetWorkflowSink(workflow, platform) - if err != nil { - return nil, err - } - if workflow == nil || sink == nil { - props.Set(constants.KnativeHealthEnabled, "false") - return props, nil - } - props.Set(constants.KnativeHealthEnabled, "true") - if workflowdef.ContainsEventKind(workflow, cncfmodel.EventKindProduced) { - props.Set(constants.KogitoOutgoingEventsConnector, constants.QuarkusHTTP) - props.Set(constants.KogitoOutgoingEventsURL, constants.KnativeInjectedEnvVar) - } - if workflowdef.ContainsEventKind(workflow, cncfmodel.EventKindConsumed) { - props.Set(constants.KogitoIncomingEventsConnector, constants.QuarkusHTTP) - props.Set(constants.KogitoIncomingEventsPath, "/") - } - return props, nil -} diff --git a/internal/controller/profiles/common/properties/managed.go b/internal/controller/profiles/common/properties/managed.go deleted file mode 100644 index a227b201..00000000 --- a/internal/controller/profiles/common/properties/managed.go +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 properties - -import ( - "context" - "fmt" - "net/url" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/persistence" - - "github.com/kubesmarts/logic-operator/utils" - - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - - "github.com/magiconair/properties" - - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -var ( - immutableApplicationProperties = fmt.Sprintf("quarkus.http.port=%d\n"+ - "quarkus.http.host=0.0.0.0\n"+ - "quarkus.devservices.enabled=false\n"+ - "quarkus.kogito.devservices.enabled=false\n", constants.DefaultHTTPWorkflowPortInt) - _ ManagedPropertyHandler = &managedPropertyHandler{} -) - -type ManagedPropertyHandler interface { - WithUserProperties(userProperties string) ManagedPropertyHandler - WithServiceDiscovery(ctx context.Context, catalog discovery.ServiceCatalog) ManagedPropertyHandler - Build() string -} - -type managedPropertyHandler struct { - workflow *operatorapi.SonataFlow - platform *operatorapi.SonataFlowPlatform - catalog discovery.ServiceCatalog - ctx context.Context - userProperties string - defaultManagedProperties *properties.Properties -} - -func (a *managedPropertyHandler) WithUserProperties(properties string) ManagedPropertyHandler { - a.userProperties = properties - return a -} - -func (a *managedPropertyHandler) WithServiceDiscovery(ctx context.Context, catalog discovery.ServiceCatalog) ManagedPropertyHandler { - a.ctx = ctx - a.catalog = catalog - return a -} - -func (a *managedPropertyHandler) Build() string { - var userProps *properties.Properties - var propErr error = nil - if len(a.userProperties) == 0 { - userProps = properties.NewProperties() - } else { - userProps, propErr = properties.LoadString(a.userProperties) - } - if propErr != nil { - klog.V(log.D).InfoS("Can't load user's property", "workflow", a.workflow.Name, "namespace", a.workflow.Namespace, "properties", a.userProperties) - userProps = properties.NewProperties() - } - // Disable expansions since it's not our responsibility - // Property expansion means resolving ${} within the properties and environment context. Quarkus will do that in runtime. - userProps.DisableExpansion = true - - // Update discovery properties - removeDiscoveryProperties(userProps) - discoveryProps := properties.NewProperties() - if a.requireServiceDiscovery() { - // produce the MicroProfileConfigServiceCatalog properties for the service discovery property values if any. - discoveryProps.Merge(generateDiscoveryProperties(a.ctx, a.catalog, userProps, a.workflow)) - } - if profiles.IsDevProfile(a.workflow) && a.requireServiceDiscovery() { - // produce dev profile properties that must be calculated at service discovery time. - setDevProfileDiscoveryProperties(a.ctx, a.catalog, a.defaultManagedProperties, a.workflow) - } - userProps = utils.NewApplicationPropertiesBuilder(). - WithInitialProperties(discoveryProps). - WithImmutableProperties(properties.MustLoadString(immutableApplicationProperties)). - WithDefaultManagedProperties(a.defaultManagedProperties). - Build() - - return userProps.String() -} - -// withKogitoServiceUrl adds the property kogitoServiceUrlProperty to the application properties. -// See Service Discovery https://kubernetes.io/docs/concepts/services-networking/service/#dns -func (a *managedPropertyHandler) withKogitoServiceUrl() ManagedPropertyHandler { - return a.addDefaultManagedProperty(constants.KogitoServiceURLProperty, GetKogitoServiceUrl(a.workflow)) -} - -func GetKogitoServiceUrl(workflow *operatorapi.SonataFlow) string { - return GetKogitoServiceUrlWithNameAndNamespace(workflow.Name, workflow.Namespace) -} - -func GetKogitoServiceUrlWithNameAndNamespace(name, namespace string) string { - if len(namespace) > 0 { - return fmt.Sprintf("%s://%s.%s", constants.DefaultHTTPProtocol, name, namespace) - } else { - return fmt.Sprintf("%s://%s", constants.DefaultHTTPProtocol, name) - } -} - -func GetWorkflowEndpointUrl(workflow *operatorapi.SonataFlow) string { - return GetWorkflowEndpointUrlWithNameAndNamespace(workflow.Name, workflow.Namespace) -} - -func GetWorkflowEndpointUrlWithNameAndNamespace(name, namespace string) string { - return GetKogitoServiceUrlWithNameAndNamespace(name, namespace) + "/" + name -} - -// withKafkaHealthCheckDisabled adds the property kafkaSmallRyeHealthProperty to the application properties. -// See Service Discovery https://kubernetes.io/docs/concepts/services-networking/service/#dns -func (a *managedPropertyHandler) withKafkaHealthCheckDisabled() ManagedPropertyHandler { - a.addDefaultManagedProperty( - constants.DataIndexKafkaHealthCheck, - "false", - ) - return a -} - -func (a *managedPropertyHandler) addDefaultManagedProperty(name string, value string) ManagedPropertyHandler { - a.defaultManagedProperties.Set(name, value) - return a -} - -// NewManagedPropertyHandler creates a property handler for a given workflow to execute in the provided platform. -// This handler is intended to build the managed application properties required by the workflow to execute properly together with -// the user properties defined in the user-managed ConfigMap. -// Note that the produced properties might vary depending on the platform, for example, if the job service managed by the platform -// have a particular set of properties will be added, etc. -// By default, the following properties are incorporated: -// The set of immutable properties provided by the operator. (user can never change) -// The set of defaultManagedProperties that are provided by the operator, and that the user cannot overwrite even if it changes -// the user-managed ConfigMap. This set includes for example the required properties to connect with the data index and the -// job service when any of these services are managed by the platform. -func NewManagedPropertyHandler(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (ManagedPropertyHandler, error) { - handler := &managedPropertyHandler{ - workflow: workflow, - platform: platform, - } - props := properties.NewProperties() - if profiles.IsDevProfile(workflow) { - setDevProfileProperties(props) - } - setControllersConfigProperties(workflow, props) - props.Set(constants.KogitoUserTasksEventsEnabled, "false") - if platform != nil { - p, err := resolvePlatformWorkflowProperties(platform) - if err != nil { - return nil, err - } - props.Merge(p) - p, err = persistence.ResolveWorkflowPersistenceProperties(workflow, platform) - if err != nil { - return nil, err - } - props.Merge(p) - p, err = services.GenerateDataIndexWorkflowProperties(workflow, platform) - if err != nil { - return nil, err - } - props.Merge(p) - p, err = services.GenerateJobServiceWorkflowProperties(workflow, platform) - if err != nil { - return nil, err - } - props.Merge(p) - } - - p, err := generateKnativeEventingWorkflowProperties(workflow, platform) - if err != nil { - return nil, err - } - props.Merge(p) - props.Sort() - - handler.defaultManagedProperties = props - return handler.withKogitoServiceUrl(), nil -} - -func setControllersConfigProperties(workflow *operatorapi.SonataFlow, props *properties.Properties) { - if !profiles.IsDevProfile(workflow) && cfg.GetCfg().KogitoEventsGrouping { - props.Set(constants.KogitoEventsGrouping, "true") - if cfg.GetCfg().KogitoEventsGroupingBinary { - props.Set(constants.KogitoEventsGroupingBinary, "true") - if cfg.GetCfg().KogitoEventsGroupingCompress { - props.Set(constants.KogitoEventsGroupingCompress, "true") - } - } - } -} - -func setDevProfileProperties(props *properties.Properties) { - props.Set(constants.QuarkusDevUICorsEnabled, "false") -} - -func setDevProfileDiscoveryProperties(ctx context.Context, catalog discovery.ServiceCatalog, props *properties.Properties, workflow *operatorapi.SonataFlow) { - if utils.IsOpenShift() { - // in OpenShift deployments the route is created before the workflow, at this point it can be queried safely. - routeUrl, err := catalog.Query(ctx, *discovery.NewResourceUriBuilder(discovery.OpenshiftScheme). - Kind("routes"). - Group("route.openshift.io"). - Version("v1"). - Namespace(workflow.Namespace). - Name(workflow.Name). - Build(), - discovery.KubernetesDNSAddress) - if err != nil { - klog.V(log.E).ErrorS(err, "An error was produced while getting workflow route url. ", "workflow", workflow.Name) - } else { - if url, err := url.Parse(routeUrl); err != nil { - klog.V(log.E).ErrorS(err, "An error was produced while parsing workflow route url. ", "workflow", workflow.Name) - } else { - props.Set(constants.QuarkusDevUIHosts, url.Host) - } - } - } -} - -// ApplicationManagedProperties immutable default application properties that can be used with any workflow based on Quarkus. -// Alias for NewManagedPropertyHandler(workflow).Build() -func ApplicationManagedProperties(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (string, error) { - p, err := NewManagedPropertyHandler(workflow, platform) - if err != nil { - return "", err - } - return p.Build(), nil -} - -func (a *managedPropertyHandler) requireServiceDiscovery() bool { - return a.ctx != nil && a.catalog != nil -} diff --git a/internal/controller/profiles/common/properties/managed_test.go b/internal/controller/profiles/common/properties/managed_test.go deleted file mode 100644 index 0b30f490..00000000 --- a/internal/controller/profiles/common/properties/managed_test.go +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 properties - -import ( - "context" - "fmt" - "testing" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - - "github.com/magiconair/properties" - - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/test" -) - -const ( - defaultNamespace = "default-namespace" - namespace1 = "namespace1" - myService1 = "my-service1" - myService1Address = "http://10.110.90.1:80" - myService2 = "my-service2" - myService2Address = "http://10.110.90.2:80" - myService3 = "my-service3" - myService3Address = "http://10.110.90.3:80" - - myKnService1 = "my-kn-service1" - myKnService1Address = "http://my-kn-sevice1.namespace1.svc.cluster.local" - - myKnService2 = "my-kn-service2" - myKnService2Address = "http://my-kn-sevice2.namespace1.svc.cluster.local" - - myKnService3 = "my-kn-service3" - myKnService3Address = "http://my-kn-sevice3.default-namespace.svc.cluster.local" - - myKnBroker1 = "my-kn-broker1" - myKnBroker1Address = "http://broker-ingress.knative-eventing.svc.cluster.local/namespace1/my-kn-broker1" - - myKnBroker2 = "my-kn-broker2" - myKnBroker2Address = "http://broker-ingress.knative-eventing.svc.cluster.local/default-namespace/my-kn-broker2" -) - -var ( - enabled = true - disabled = false -) - -type mockCatalogService struct { -} - -func (c *mockCatalogService) Query(ctx context.Context, uri discovery.ResourceUri, outputFormat string) (string, error) { - if uri.Scheme == discovery.KubernetesScheme && uri.Namespace == namespace1 && uri.Name == myService1 { - return myService1Address, nil - } - if uri.Scheme == discovery.KubernetesScheme && uri.Name == myService2 && uri.Namespace == defaultNamespace { - return myService2Address, nil - } - if uri.Scheme == discovery.KubernetesScheme && uri.Name == myService3 && uri.Namespace == defaultNamespace && uri.GetPort() == "http-port" { - return myService3Address, nil - } - if uri.Scheme == discovery.KnativeScheme && uri.Name == myKnService1 && uri.Namespace == namespace1 { - return myKnService1Address, nil - } - if uri.Scheme == discovery.KnativeScheme && uri.Name == myKnService2 && uri.Namespace == namespace1 { - return myKnService2Address, nil - } - if uri.Scheme == discovery.KnativeScheme && uri.Name == myKnService3 && uri.Namespace == defaultNamespace { - return myKnService3Address, nil - } - if uri.Scheme == discovery.KnativeScheme && uri.Name == myKnBroker1 && uri.Namespace == namespace1 { - return myKnBroker1Address, nil - } - if uri.Scheme == discovery.KnativeScheme && uri.Name == myKnBroker2 && uri.Namespace == defaultNamespace { - return myKnBroker2Address, nil - } - - return "", nil -} - -func Test_appPropertyHandler_WithKogitoServiceUrl(t *testing.T) { - workflow := test.GetBaseSonataFlow("default") - platform := test.GetBasePlatform() - props, err := ApplicationManagedProperties(workflow, platform) - assert.NoError(t, err) - assert.Contains(t, props, constants.KogitoServiceURLProperty) - assert.Contains(t, props, "http://"+workflow.Name+"."+workflow.Namespace) -} - -func Test_appPropertyHandler_WithUserPropertiesWithNoUserOverrides(t *testing.T) { - //just add some user provided properties, no overrides. - userProperties := "property1=value1\nproperty2=value2" - workflow := test.GetBaseSonataFlow("default") - platform := test.GetBasePlatform() - props, err := NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr := properties.LoadString(props.WithUserProperties(userProperties).Build()) - assert.NoError(t, propsErr) - assert.Equal(t, 14, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - assert.Equal(t, "http://greeting.default", generatedProps.GetString("kogito.service.url", "")) - assert.Equal(t, "8080", generatedProps.GetString("quarkus.http.port", "")) - assert.Equal(t, "0.0.0.0", generatedProps.GetString("quarkus.http.host", "")) - assert.Equal(t, "false", generatedProps.GetString("quarkus.devservices.enabled", "")) - assert.Equal(t, "false", generatedProps.GetString("quarkus.kogito.devservices.enabled", "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoUserTasksEventsEnabled, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsEnabled, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessInstancesEventsEnabled, "")) - assert.Equal(t, "quarkus-http", generatedProps.GetString("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "")) - assert.Equal(t, "http://localhost/v2/jobs/events", generatedProps.GetString("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "")) - assert.Equal(t, "false", generatedProps.GetString("org.kie.kogito.addons.knative.eventing.health-enabled", "")) -} - -func Test_appPropertyHandler_WithUserPropertiesWithServiceDiscovery(t *testing.T) { - //just add some user provided properties, no overrides. - userProperties := "property1=value1\nproperty2=value2\n" - //add some user properties that requires service discovery - userProperties = userProperties + "service1=${kubernetes:services.v1/namespace1/my-service1}\n" - userProperties = userProperties + "service2=${kubernetes:services.v1/my-service2}\n" - userProperties = userProperties + "service3=${knative:namespace1/my-kn-service1}\n" - userProperties = userProperties + "service4=${knative:services.v1.serving.knative.dev/namespace1/my-kn-service2}\n" - userProperties = userProperties + "service5=${knative:services.v1.serving.knative.dev/my-kn-service3}\n" - userProperties = userProperties + "broker1=${knative:brokers.v1.eventing.knative.dev/namespace1/my-kn-broker1}\n" - userProperties = userProperties + "broker2=${knative:brokers.v1.eventing.knative.dev/my-kn-broker2}\n" - - workflow := test.GetBaseSonataFlow(defaultNamespace) - platform := test.GetBasePlatform() - props, err := NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr := properties.LoadString(props. - WithUserProperties(userProperties). - WithServiceDiscovery(context.TODO(), &mockCatalogService{}). - Build()) - generatedProps.DisableExpansion = true - assert.NoError(t, propsErr) - assert.Equal(t, 28, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - assertHasProperty(t, generatedProps, "service1", myService1Address) - assertHasProperty(t, generatedProps, "service2", myService2Address) - assertHasProperty(t, generatedProps, "service3", myKnService1Address) - assertHasProperty(t, generatedProps, "service4", myKnService2Address) - assertHasProperty(t, generatedProps, "service5", myKnService3Address) - assertHasProperty(t, generatedProps, "broker1", myKnBroker1Address) - assertHasProperty(t, generatedProps, "broker2", myKnBroker2Address) - - //org.kie.kogito.addons.discovery.kubernetes\:services.v1\/usecase1º/my-service1 below we use the unescaped vale because the properties.LoadString removes them. - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.kubernetes:services.v1/namespace1/my-service1", myService1Address) - //org.kie.kogito.addons.discovery.kubernetes\:services.v1\/my-service2 below we use the unescaped vale because the properties.LoadString removes them. - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.kubernetes:services.v1/my-service2", myService2Address) - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.knative:namespace1/my-kn-service1", myKnService1Address) - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.knative:services.v1.serving.knative.dev/namespace1/my-kn-service2", myKnService2Address) - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.knative:services.v1.serving.knative.dev/my-kn-service3", myKnService3Address) - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.knative:brokers.v1.eventing.knative.dev/namespace1/my-kn-broker1", myKnBroker1Address) - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.discovery.knative:brokers.v1.eventing.knative.dev/my-kn-broker2", myKnBroker2Address) - - assertHasProperty(t, generatedProps, "kogito.service.url", fmt.Sprintf("http://greeting.%s", defaultNamespace)) - assertHasProperty(t, generatedProps, "quarkus.http.port", "8080") - assertHasProperty(t, generatedProps, "quarkus.http.host", "0.0.0.0") - assertHasProperty(t, generatedProps, "quarkus.devservices.enabled", "false") - assertHasProperty(t, generatedProps, "quarkus.kogito.devservices.enabled", "false") - assertHasProperty(t, generatedProps, constants.KogitoUserTasksEventsEnabled, "false") - - assertHasProperty(t, generatedProps, "org.kie.kogito.addons.knative.eventing.health-enabled", "false") - assertHasProperty(t, generatedProps, "kogito.events.processdefinitions.enabled", "false") - assertHasProperty(t, generatedProps, "kogito.events.processinstances.enabled", "false") - assertHasProperty(t, generatedProps, "kogito.events.usertasks.enabled", "false") - assertHasProperty(t, generatedProps, "mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - assertHasProperty(t, generatedProps, "mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") -} - -func Test_appPropertyHandler_WithServicesWithUserOverrides(t *testing.T) { - //try to override kogito.service.url and quarkus.http.port - userProperties := "property1=value1\nproperty2=value2\nquarkus.http.port=9090\nkogito.service.url=http://myUrl.override.com\nquarkus.http.port=9090" - ns := "default" - workflow := test.GetBaseSonataFlow(ns) - workflow.SetAnnotations(map[string]string{metadata.Profile: string(metadata.DevProfile)}) - enabled := true - platform := test.GetBasePlatform() - platform.Namespace = ns - platform.Spec = operatorapi.SonataFlowPlatformSpec{ - Services: &operatorapi.ServicesPlatformSpec{ - DataIndex: &operatorapi.DataIndexServiceSpec{ - ServiceSpec: operatorapi.ServiceSpec{ - Enabled: &enabled, - }, - }, - JobService: &operatorapi.JobServiceServiceSpec{ - ServiceSpec: operatorapi.ServiceSpec{ - Enabled: &enabled, - }, - }, - }, - } - - services.SetServiceUrlsInWorkflowStatus(platform, workflow) - assert.Nil(t, workflow.Status.Services) - props, err := NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr := properties.LoadString(props.WithUserProperties(userProperties).Build()) - assert.NoError(t, propsErr) - assert.Equal(t, 12, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - - //kogito.service.url is a default immutable property. - assert.Equal(t, "http://greeting.default", generatedProps.GetString("kogito.service.url", "")) - //quarkus.http.port remains with the default value since it's immutable. - assert.Equal(t, "8080", generatedProps.GetString("quarkus.http.port", "")) - assert.Equal(t, "0.0.0.0", generatedProps.GetString("quarkus.http.host", "")) - assert.Equal(t, "false", generatedProps.GetString("org.kie.kogito.addons.knative.eventing.health-enabled", "")) - assert.Equal(t, "false", generatedProps.GetString("quarkus.devservices.enabled", "")) - assert.Equal(t, "false", generatedProps.GetString("quarkus.kogito.devservices.enabled", "")) - assert.Equal(t, "http://localhost/v2/jobs/events", generatedProps.GetString(constants.JobServiceRequestEventsURL, "")) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsEnabled, "")) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessInstancesEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessInstancesEventsEnabled, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoUserTasksEventsEnabled, "")) - - // prod profile enables config of outgoing events url - workflow.SetAnnotations(map[string]string{metadata.Profile: string(metadata.PreviewProfile)}) - services.SetServiceUrlsInWorkflowStatus(platform, workflow) - assert.NotNil(t, workflow.Status.Services) - assert.NotNil(t, workflow.Status.Services.JobServiceRef) - assert.NotNil(t, workflow.Status.Services.DataIndexRef) - props, err = NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr = properties.LoadString(props.WithUserProperties(userProperties).Build()) - assert.NoError(t, propsErr) - assert.Equal(t, 19, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - assert.Equal(t, "http://"+platform.Name+"-"+constants.DataIndexServiceName+"."+platform.Namespace+"/definitions", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsURL, "")) - assert.Equal(t, "true", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsEnabled, "")) - assert.Equal(t, "true", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsErrorsEnabled, "")) - assert.Equal(t, "http://"+platform.Name+"-"+constants.DataIndexServiceName+"."+platform.Namespace+"/processes", generatedProps.GetString(constants.KogitoProcessInstancesEventsURL, "")) - assert.Equal(t, "true", generatedProps.GetString(constants.KogitoProcessInstancesEventsEnabled, "")) - assert.Equal(t, "http://"+platform.Name+"-"+constants.JobServiceName+"."+platform.Namespace+"/v2/jobs/events", generatedProps.GetString(constants.JobServiceRequestEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoUserTasksEventsEnabled, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceDataSourceReactiveURL, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEvents, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEventsURL, "")) - assert.Equal(t, "true", generatedProps.GetString(constants.KogitoDataIndexHealthCheckEnabled, "")) - assert.Equal(t, "http://"+platform.Name+"-"+constants.DataIndexServiceName+"."+platform.Namespace, generatedProps.GetString(constants.KogitoDataIndexURL, "")) - assert.Equal(t, "http://"+platform.Name+"-"+constants.JobServiceName+"."+platform.Namespace, generatedProps.GetString(constants.KogitoJobServiceURL, "")) - - // disabling data index bypasses config of outgoing events url - platform.Spec.Services.DataIndex.Enabled = nil - services.SetServiceUrlsInWorkflowStatus(platform, workflow) - assert.NotNil(t, workflow.Status.Services) - assert.NotNil(t, workflow.Status.Services.JobServiceRef) - assert.Nil(t, workflow.Status.Services.DataIndexRef) - props, err = NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr = properties.LoadString(props.WithUserProperties(userProperties).Build()) - assert.NoError(t, propsErr) - assert.Equal(t, 14, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsEnabled, "")) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessInstancesEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessInstancesEventsEnabled, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoUserTasksEventsEnabled, "")) - assert.Equal(t, "http://"+platform.Name+"-"+constants.JobServiceName+"."+platform.Namespace+"/v2/jobs/events", generatedProps.GetString(constants.JobServiceRequestEventsURL, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEvents, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEventsURL, "")) - - // disabling job service bypasses config of outgoing events url - platform.Spec.Services.JobService.Enabled = nil - services.SetServiceUrlsInWorkflowStatus(platform, workflow) - assert.Nil(t, workflow.Status.Services) - props, err = NewManagedPropertyHandler(workflow, platform) - assert.NoError(t, err) - generatedProps, propsErr = properties.LoadString(props.WithUserProperties(userProperties).Build()) - assert.NoError(t, propsErr) - assert.Equal(t, 13, len(generatedProps.Keys())) - assert.NotContains(t, "property1", generatedProps.Keys()) - assert.NotContains(t, "property2", generatedProps.Keys()) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessDefinitionsEventsEnabled, "")) - assert.Equal(t, "", generatedProps.GetString(constants.KogitoProcessInstancesEventsURL, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoProcessInstancesEventsEnabled, "")) - assert.Equal(t, "false", generatedProps.GetString(constants.KogitoUserTasksEventsEnabled, "")) - assert.Equal(t, "http://localhost/v2/jobs/events", generatedProps.GetString(constants.JobServiceRequestEventsURL, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceDataSourceReactiveURL, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEvents, "")) - assert.Equal(t, "", generatedProps.GetString(constants.JobServiceStatusChangeEventsURL, "")) -} - -type eventsGroupingTestSpec struct { - kogitoEventsGrouping bool - kogitoEventsGroupingBinary bool - kogitoEventsGroupingCompress bool - shouldContainEventsGrouping bool - shouldContainEventsGroupingBinary bool - shouldContainEventsGroupingCompress bool -} - -func newTestSpec(eventsGrouping bool, eventsGroupingBinary bool, eventsGroupingCompress bool, - shouldContainEventsGrouping bool, shouldContainEventsGroupingBinary bool, shouldContainEventsGroupingCompress bool) *eventsGroupingTestSpec { - return &eventsGroupingTestSpec{ - kogitoEventsGrouping: eventsGrouping, - kogitoEventsGroupingBinary: eventsGroupingBinary, - kogitoEventsGroupingCompress: eventsGroupingCompress, - shouldContainEventsGrouping: shouldContainEventsGrouping, - shouldContainEventsGroupingBinary: shouldContainEventsGroupingBinary, - shouldContainEventsGroupingCompress: shouldContainEventsGroupingCompress, - } -} -func Test_appPropertyHandler_KogitoEventsGroupingTrueWithDevProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.DevProfile, newTestSpec(false, false, false, false, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueWithPreviewProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.PreviewProfile, newTestSpec(true, false, false, true, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueWithGitOpsProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.GitOpsProfile, newTestSpec(true, false, false, true, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingFalseWithDevProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.DevProfile, newTestSpec(false, false, false, false, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingFalseWithPreviewProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.PreviewProfile, newTestSpec(false, false, false, false, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueBinaryTrueCompressFalseWithPreviewProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.PreviewProfile, newTestSpec(true, true, false, true, true, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueBinaryTrueCompressTrueWithPreviewProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.PreviewProfile, newTestSpec(true, true, true, true, true, true)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingFalseWithGitOpsProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.GitOpsProfile, newTestSpec(false, false, false, false, false, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueBinaryTrueCompressFalseWithGitOpsProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.GitOpsProfile, newTestSpec(true, true, false, true, true, false)) -} - -func Test_appPropertyHandler_KogitoEventsGroupingTrueBinaryTrueCompressTrueWithGitOpsProfile(t *testing.T) { - doTestManagedPropsForKogitoEventsGrouping(t, metadata.GitOpsProfile, newTestSpec(true, true, true, true, true, true)) -} - -func doTestManagedPropsForKogitoEventsGrouping(t *testing.T, profile metadata.ProfileType, testSpec *eventsGroupingTestSpec) { - currentKogitoEventGroupingValue := cfg.GetCfg().KogitoEventsGrouping - currentKogitoEventGroupingBinaryValue := cfg.GetCfg().KogitoEventsGroupingBinary - currentKogitoEventGroupingCompressValue := cfg.GetCfg().KogitoEventsGroupingCompress - cfg.GetCfg().KogitoEventsGrouping = testSpec.kogitoEventsGrouping - cfg.GetCfg().KogitoEventsGroupingBinary = testSpec.kogitoEventsGroupingBinary - cfg.GetCfg().KogitoEventsGroupingCompress = testSpec.kogitoEventsGroupingCompress - workflow := test.GetBaseSonataFlow("default") - setProfileInFlow(profile)(workflow) - platform := test.GetBasePlatform() - handler, err := NewManagedPropertyHandler(workflow, platform) - cfg.GetCfg().KogitoEventsGrouping = currentKogitoEventGroupingValue - cfg.GetCfg().KogitoEventsGroupingBinary = currentKogitoEventGroupingBinaryValue - cfg.GetCfg().KogitoEventsGroupingCompress = currentKogitoEventGroupingCompressValue - assert.NoError(t, err) - generatedProps, propsErr := properties.LoadString(handler.Build()) - assert.NoError(t, propsErr) - if testSpec.shouldContainEventsGrouping { - assertHasProperty(t, generatedProps, "kogito.events.grouping", "true") - } else { - assert.NotContains(t, generatedProps.Keys(), "kogito.events.grouping") - } - if testSpec.shouldContainEventsGroupingBinary { - assertHasProperty(t, generatedProps, "kogito.events.grouping.binary", "true") - } else { - assert.NotContains(t, generatedProps.Keys(), "kogito.events.grouping.binary", "true") - } - if testSpec.shouldContainEventsGroupingCompress { - assertHasProperty(t, generatedProps, "kogito.events.grouping.compress", "true") - } else { - assert.NotContains(t, generatedProps.Keys(), "kogito.events.grouping.compress", "true") - } -} - -var _ = Describe("Platform properties", func() { - - var _ = Context("for workflow properties", func() { - - var _ = Context("defining the workflow properties generated from", func() { - - DescribeTable("only job services when the spec", - func(wf *operatorapi.SonataFlow, plfm *operatorapi.SonataFlowPlatform, expectedProperties *properties.Properties) { - services.SetServiceUrlsInWorkflowStatus(plfm, wf) - handler, err := NewManagedPropertyHandler(wf, plfm) - Expect(err).NotTo(HaveOccurred()) - p, err := properties.LoadString(handler.Build()) - Expect(err).NotTo(HaveOccurred()) - p.Sort() - Expect(p).To(Equal(expectedProperties)) - }, - Entry("has enabled field set to false and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateJobServiceWorkflowDevProperties()), - Entry("has enabled field set to false and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateJobServiceWorkflowProductionWithJobServiceDisabled()), - Entry("has enabled field undefined and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setPlatformNamespace("default"), setPlatformName("foo")), - generateJobServiceWorkflowDevProperties()), - Entry("has enabled field undefined and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setPlatformNamespace("default"), setPlatformName("foo")), - generateJobServiceWorkflowProductionWithJobServiceDisabled()), - Entry("has enabled field set to true and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceWorkflowDevProperties()), - Entry("has enabled field set to true and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceWorkflowProductionProperties()), - Entry("has enabled field set to true and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceWorkflowProductionProperties()), - Entry("has enabled field set to false and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceWorkflowProductionWithJobServiceDisabled()), - Entry("has enabled field undefined and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default")), - generateJobServiceWorkflowProductionWithJobServiceDisabled()), - ) - - DescribeTable("only data index service when the spec", - func(wf *operatorapi.SonataFlow, plfm *operatorapi.SonataFlowPlatform, expectedProperties *properties.Properties) { - services.SetServiceUrlsInWorkflowStatus(plfm, wf) - handler, err := NewManagedPropertyHandler(wf, plfm) - Expect(err).NotTo(HaveOccurred()) - p, err := properties.LoadString(handler.Build()) - Expect(err).NotTo(HaveOccurred()) - p.Sort() - Expect(p).To(Equal(expectedProperties)) - }, - Entry("has enabled field set to false and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&disabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowDevProperties()), - Entry("has enabled field set to false and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&disabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionPropertiesWithDataIndexDisabled()), - Entry("has enabled field undefined and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(nil), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowDevProperties()), - Entry("has enabled field undefined and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(nil), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionPropertiesWithDataIndexDisabled()), - Entry("has enabled field set to true and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&enabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowDevProperties()), - Entry("has enabled field set to true and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&enabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionProperties()), - Entry("has enabled field set to false and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&disabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionPropertiesWithDataIndexDisabled()), - Entry("has enabled field set to true and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(&enabled), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionProperties()), - Entry("has enabled field undefined and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setDataIndexEnabledValue(nil), setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexWorkflowProductionPropertiesWithDataIndexDisabled()), - ) - - DescribeTable("both Data Index and Job Services are available and", func(wf *operatorapi.SonataFlow, plfm *operatorapi.SonataFlowPlatform, expectedProperties *properties.Properties) { - services.SetServiceUrlsInWorkflowStatus(plfm, wf) - handler, err := NewManagedPropertyHandler(wf, plfm) - Expect(err).NotTo(HaveOccurred()) - p, err := properties.LoadString(handler.Build()) - Expect(err).NotTo(HaveOccurred()) - p.Sort() - Expect(p).To(Equal(expectedProperties)) - }, - Entry("both are undefined and workflow in dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexAndJobServiceWorkflowDevProperties()), - Entry("both are undefined and workflow in prod profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setPlatformNamespace("default"), setPlatformName("foo")), - generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled()), - Entry("both have enabled field set to true and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setDataIndexEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateDataIndexAndJobServiceWorkflowDevProperties()), - Entry("both have enabled field set to true and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setDataIndexEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default")), - generateDataIndexAndJobServiceWorkflowProductionProperties()), - Entry("both have enabled field undefined and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setDataIndexEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default")), - generateDataIndexAndJobServiceWorkflowDevProperties()), - Entry("both have enabled field undefined and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setDataIndexEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled()), - Entry("both have enabled field set to false and workflow with dev profile", - generateFlow(setProfileInFlow(metadata.DevProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setDataIndexEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowDevProperties()), - Entry("both have enabled field set to false and workflow with production profile", - generateFlow(setProfileInFlow(metadata.PreviewProfile), setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setDataIndexEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled()), - Entry("both have enabled field set to false and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&disabled), setDataIndexEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled()), - Entry("both have enabled field set to true and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(&enabled), setDataIndexEnabledValue(&enabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowProductionProperties()), - Entry("both have enabled field undefined and workflow with no profile", - generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), - generatePlatform(setJobServiceEnabledValue(nil), setDataIndexEnabledValue(&disabled), setPlatformName("foo"), setPlatformNamespace("default"), setJobServiceJDBC("jdbc:postgresql://postgres:5432/sonataflow?currentSchema=myschema")), - generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled()), - ) - }) - }) - -}) - -func generateJobServiceWorkflowDevProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.devservices.enabled", "false") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("quarkus.dev-ui.cors.enabled", "false") - props.Sort() - return props -} - -func generateJobServiceWorkflowProductionWithJobServiceDisabled() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.devservices.enabled", "false") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props -} - -func generateJobServiceWorkflowProductionProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("kogito.jobs-service.url", "http://foo-jobs-service.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("quarkus.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://foo-jobs-service.default/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props -} - -func generateDataIndexWorkflowDevProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.devservices.enabled", "false") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("quarkus.dev-ui.cors.enabled", "false") - props.Sort() - return props -} - -func generateDataIndexWorkflowProductionPropertiesWithDataIndexDisabled() *properties.Properties { - props := properties.NewProperties() - props = properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.devservices.enabled", "false") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props -} - -func generateDataIndexWorkflowProductionProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("kogito.data-index.url", "http://foo-data-index-service.default") - props.Set("kogito.data-index.health-enabled", "true") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.devservices.enabled", "false") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("mp.messaging.outgoing.kogito-processdefinitions-events.url", "http://foo-data-index-service.default/definitions") - props.Set("mp.messaging.outgoing.kogito-processinstances-events.url", "http://foo-data-index-service.default/processes") - props.Set("kogito.events.processdefinitions.enabled", "true") - props.Set("kogito.events.processdefinitions.errors.propagate", "true") - props.Set("kogito.events.processinstances.enabled", "true") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props -} - -func generateDataIndexAndJobServiceWorkflowDevProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("quarkus.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("quarkus.dev-ui.cors.enabled", "false") - props.Sort() - return props -} - -func generateDataIndexAndJobServiceWorkflowProductionDataIndexAndJobsServiceDisabled() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("quarkus.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "false") - props.Set("kogito.events.processinstances.enabled", "false") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props -} - -func generateDataIndexAndJobServiceWorkflowProductionProperties() *properties.Properties { - props := properties.NewProperties() - props.Set("kogito.service.url", "http://foo.default") - props.Set("kogito.data-index.url", "http://foo-data-index-service.default") - props.Set("kogito.data-index.health-enabled", "true") - props.Set("kogito.jobs-service.url", "http://foo-jobs-service.default") - props.Set("quarkus.http.host", "0.0.0.0") - props.Set("quarkus.http.port", "8080") - props.Set("quarkus.kogito.devservices.enabled", "false") - props.Set("quarkus.devservices.enabled", "false") - props.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") - props.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://foo-jobs-service.default/v2/jobs/events") - props.Set("kogito.events.processdefinitions.enabled", "true") - props.Set("kogito.events.processdefinitions.errors.propagate", "true") - props.Set("kogito.events.processinstances.enabled", "true") - props.Set("kogito.events.usertasks.enabled", "false") - props.Set("mp.messaging.outgoing.kogito-processdefinitions-events.url", "http://foo-data-index-service.default/definitions") - props.Set("mp.messaging.outgoing.kogito-processinstances-events.url", "http://foo-data-index-service.default/processes") - props.Set("kogito.events.grouping", "true") - props.Set("kogito.events.grouping.binary", "true") - props.Sort() - return props - -} - -type wfOptionFn func(wf *operatorapi.SonataFlow) - -func generateFlow(opts ...wfOptionFn) *operatorapi.SonataFlow { - wf := &operatorapi.SonataFlow{} - for _, f := range opts { - f(wf) - } - return wf -} - -func setProfileInFlow(p metadata.ProfileType) wfOptionFn { - return func(wf *operatorapi.SonataFlow) { - if wf.Annotations == nil { - wf.Annotations = make(map[string]string) - } - wf.Annotations[metadata.Profile] = p.String() - } -} - -func setWorkflowName(n string) wfOptionFn { - return func(wf *operatorapi.SonataFlow) { - wf.Name = n - } -} - -func setWorkflowNamespace(ns string) wfOptionFn { - return func(wf *operatorapi.SonataFlow) { - wf.Namespace = ns - } -} - -type plfmOptionFn func(p *operatorapi.SonataFlowPlatform) - -func generatePlatform(opts ...plfmOptionFn) *operatorapi.SonataFlowPlatform { - plfm := &operatorapi.SonataFlowPlatform{} - for _, f := range opts { - f(plfm) - } - return plfm -} - -func setJobServiceEnabledValue(v *bool) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.JobService == nil { - p.Spec.Services.JobService = &operatorapi.JobServiceServiceSpec{} - } - p.Spec.Services.JobService.Enabled = v - } -} - -func setDataIndexEnabledValue(v *bool) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.DataIndex == nil { - p.Spec.Services.DataIndex = &operatorapi.DataIndexServiceSpec{} - } - p.Spec.Services.DataIndex.Enabled = v - } -} - -func setPlatformNamespace(namespace string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - p.Namespace = namespace - } -} - -func setPlatformName(name string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - p.Name = name - } -} - -func setJobServiceJDBC(jdbc string) plfmOptionFn { - return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } - if p.Spec.Services.JobService == nil { - p.Spec.Services.JobService = &operatorapi.JobServiceServiceSpec{} - } - if p.Spec.Services.JobService.Persistence == nil { - p.Spec.Services.JobService.Persistence = &operatorapi.PersistenceOptionsSpec{} - } - if p.Spec.Services.JobService.Persistence.PostgreSQL == nil { - p.Spec.Services.JobService.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} - } - p.Spec.Services.JobService.Persistence.PostgreSQL.JdbcUrl = jdbc - } -} diff --git a/internal/controller/profiles/common/properties/platform.go b/internal/controller/profiles/common/properties/platform.go deleted file mode 100644 index 4f98513a..00000000 --- a/internal/controller/profiles/common/properties/platform.go +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 properties - -import ( - "context" - - "github.com/magiconair/properties" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" -) - -func resolvePlatformWorkflowProperties(platform *operatorapi.SonataFlowPlatform) (*properties.Properties, error) { - props := properties.NewProperties() - - if platform.Spec.Properties == nil { - return props, nil - } - - for _, propVar := range platform.Spec.Properties.Flow { - if len(propVar.Value) > 0 { - props.Set(propVar.Name, propVar.Value) - } else if propVar.ValueFrom != nil { - val, err := getPropVarRefValue(propVar.ValueFrom, platform.Namespace) - if err != nil { - return nil, err - } - props.Set(propVar.Name, val) - } - } - - return props, nil -} - -func getPropVarRefValue(from *operatorapi.PropertyVarSource, namespace string) (string, error) { - // same order as k8s api (we try to fetch first a secret) - if from.SecretKeyRef != nil { - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: from.SecretKeyRef.Name}, - } - err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}, secret) - if err != nil && !errors.IsNotFound(err) { - return "", err - } - if data, ok := secret.Data[from.SecretKeyRef.Key]; ok { - return string(data), nil - } - if from.SecretKeyRef.Optional == utils.Pbool(false) { - klog.V(log.D).InfoS("Key not found in secret", "Key", from.SecretKeyRef.Key) - } - } - if from.ConfigMapKeyRef != nil { - cm := &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: from.ConfigMapKeyRef.Name}, - } - err := utils.GetClient().Get(context.TODO(), types.NamespacedName{Namespace: cm.Namespace, Name: cm.Name}, cm) - if err != nil && !errors.IsNotFound(err) { - return "", err - } - if data, ok := cm.Data[from.ConfigMapKeyRef.Key]; ok { - return data, nil - } - if from.ConfigMapKeyRef.Optional == utils.Pbool(false) { - klog.V(log.D).InfoS("Key not found in configMap", "Key", from.ConfigMapKeyRef.Key) - } - } - - return "", nil -} diff --git a/internal/controller/profiles/common/properties/platform_test.go b/internal/controller/profiles/common/properties/platform_test.go deleted file mode 100644 index 8f099480..00000000 --- a/internal/controller/profiles/common/properties/platform_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 properties - -import ( - "testing" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test" -) - -func Test_resolvePlatformWorkflowProperties(t *testing.T) { - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{Name: "secretPlatformTest", Namespace: t.Name()}, - Data: map[string][]byte{"my-key": []byte("secret")}, - } - cm := &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Name: "configMapPlatformTest", Namespace: t.Name()}, - Data: map[string]string{"my-key": "value"}, - } - - platform := test.GetBasePlatform() - platform.Namespace = t.Name() - platform.Spec.Properties = &v1alpha08.PropertyPlatformSpec{ - Flow: []v1alpha08.PropertyVar{ - { - Name: "quarkus.log.category", - Value: "DEBUG", - }, - { - Name: "quarkus.custom.property", - ValueFrom: &v1alpha08.PropertyVarSource{ - ConfigMapKeyRef: &v1.ConfigMapKeySelector{ - Key: "my-key", - LocalObjectReference: v1.LocalObjectReference{Name: "configMapPlatformTest"}, - }, - }, - }, - { - Name: "quarkus.custom.secret", - ValueFrom: &v1alpha08.PropertyVarSource{ - SecretKeyRef: &v1.SecretKeySelector{ - Key: "my-key", - LocalObjectReference: v1.LocalObjectReference{Name: "secretPlatformTest"}, - }, - }, - }, - }, - } - - _ = test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform, secret, cm).WithStatusSubresource(platform).Build() - - props, err := resolvePlatformWorkflowProperties(platform) - assert.NoError(t, err) - assert.NotNil(t, props) - - assertHasProperty(t, props, "quarkus.log.category", "DEBUG") - assertHasProperty(t, props, "quarkus.custom.property", "value") - assertHasProperty(t, props, "quarkus.custom.secret", "secret") -} - -func Test_resolvePlatformWorkflowProperties_RefNotFound(t *testing.T) { - platform := test.GetBasePlatform() - platform.Namespace = t.Name() - platform.Spec.Properties = &v1alpha08.PropertyPlatformSpec{ - Flow: []v1alpha08.PropertyVar{ - { - Name: "quarkus.log.category", - Value: "DEBUG", - }, - { - Name: "quarkus.custom.property", - ValueFrom: &v1alpha08.PropertyVarSource{ - ConfigMapKeyRef: &v1.ConfigMapKeySelector{ - Key: "my-key", - LocalObjectReference: v1.LocalObjectReference{Name: "configMapPlatformTest"}, - }, - }, - }, - { - Name: "quarkus.custom.secret", - ValueFrom: &v1alpha08.PropertyVarSource{ - SecretKeyRef: &v1.SecretKeySelector{ - Key: "my-key", - LocalObjectReference: v1.LocalObjectReference{Name: "secretPlatformTest"}, - }, - }, - }, - }, - } - - _ = test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform).WithStatusSubresource(platform).Build() - - props, err := resolvePlatformWorkflowProperties(platform) - assert.NoError(t, err) - assert.NotNil(t, props) - - assertHasProperty(t, props, "quarkus.log.category", "DEBUG") - assertHasProperty(t, props, "quarkus.custom.property", "") - assertHasProperty(t, props, "quarkus.custom.secret", "") -} diff --git a/internal/controller/profiles/common/properties/properties_suite_test.go b/internal/controller/profiles/common/properties/properties_suite_test.go deleted file mode 100644 index 214384f7..00000000 --- a/internal/controller/profiles/common/properties/properties_suite_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 properties_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestProperties(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Properties Suite") -} diff --git a/internal/controller/profiles/common/properties/properties_test.go b/internal/controller/profiles/common/properties/properties_test.go deleted file mode 100644 index 54d48260..00000000 --- a/internal/controller/profiles/common/properties/properties_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 properties - -import ( - "testing" - - "github.com/magiconair/properties" - "github.com/stretchr/testify/assert" -) - -func assertHasProperty(t *testing.T, props *properties.Properties, expectedProperty string, expectedValue string) { - value, ok := props.Get(expectedProperty) - assert.True(t, ok, "Property %s, is not present as expected.", expectedProperty) - assert.Equal(t, expectedValue, value, "Expected value for property: %s, is: %s but current value is: %s", expectedProperty, expectedValue, value) -} diff --git a/internal/controller/profiles/common/reconciler.go b/internal/controller/profiles/common/reconciler.go deleted file mode 100644 index e3d27f15..00000000 --- a/internal/controller/profiles/common/reconciler.go +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - - "github.com/kubesmarts/logic-operator/utils" - - "k8s.io/client-go/rest" - - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - - "k8s.io/client-go/tools/record" - - klog "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/log" -) - -// StateSupport is the shared structure with common accessors used throughout the whole reconciliation profiles -type StateSupport struct { - C client.Client - Cfg *rest.Config - Catalog discovery.ServiceCatalog - Recorder record.EventRecorder -} - -// PerformStatusUpdate updates the SonataFlow Status conditions -func (s *StateSupport) PerformStatusUpdate(ctx context.Context, workflow *operatorapi.SonataFlow) (bool, error) { - var err error - pl, err := platform.GetActivePlatform(ctx, s.C, workflow.Namespace, true) - if err != nil { - return false, err - } - workflow.Status.ObservedGeneration = workflow.Generation - workflow.Status.FlowCRC, err = utils.Crc32Checksum(workflow.Spec.Flow) - if err != nil { - return false, err - } - services.SetServiceUrlsInWorkflowStatus(pl, workflow) - if workflow.Status.Platform == nil { - workflow.Status.Platform = &operatorapi.SonataFlowPlatformRef{} - } - workflow.Status.Platform.Name = pl.Name - workflow.Status.Platform.Namespace = pl.Namespace - - if err = s.C.Status().Update(ctx, workflow); err != nil { - klog.V(log.E).ErrorS(err, "Failed to update Workflow status") - return false, err - } - return true, err -} - -// Reconciler is the base structure used by every reconciliation profile. -// Use NewReconciler to build a new reference. -type Reconciler struct { - *StateSupport - reconciliationStateMachine *ReconciliationStateMachine - objects []client.Object -} - -func NewReconciler(support *StateSupport, stateMachine *ReconciliationStateMachine) Reconciler { - return Reconciler{ - StateSupport: support, - reconciliationStateMachine: stateMachine, - } -} - -// Reconcile does the actual reconciliation algorithm based on a set of ReconciliationState -func (b *Reconciler) Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) { - workflow.Status.Manager().InitializeConditions() - result, objects, err := b.reconciliationStateMachine.do(ctx, workflow) - if err != nil { - return result, err - } - b.objects = objects - klog.V(log.I).InfoS("Returning from reconciliation", "Result", result) - - return result, err -} - -// NewReconciliationStateMachine builder for the ReconciliationStateMachine -func NewReconciliationStateMachine(states ...profiles.ReconciliationState) *ReconciliationStateMachine { - return &ReconciliationStateMachine{ - states: states, - } -} - -// ReconciliationStateMachine implements (sort of) the command pattern and delegate to a chain of ReconciliationState -// the actual task to reconcile in a given workflow condition -// -// TODO: implement state transition, so based on a given condition we do the status update which actively transition the object state -type ReconciliationStateMachine struct { - states []profiles.ReconciliationState -} - -func (r *ReconciliationStateMachine) do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - for _, h := range r.states { - if h.CanReconcile(workflow) { - klog.V(log.I).InfoS("Found a condition to reconcile.", "Conditions", workflow.Status.Conditions) - result, objs, err := h.Do(ctx, workflow) - if err != nil { - return result, objs, err - } - if err = h.PostReconcile(ctx, workflow); err != nil { - klog.V(log.E).ErrorS(err, "Error in Post Reconcile actions.", "Workflow", workflow.Name, "Conditions", workflow.Status.Conditions) - } - return result, objs, err - } - } - return ctrl.Result{}, nil, fmt.Errorf("the workflow %s in the namespace %s is in an unknown state condition. Can't reconcilie. Status is: %v", workflow.Name, workflow.Namespace, workflow.Status) -} diff --git a/internal/controller/profiles/common/status_enricher.go b/internal/controller/profiles/common/status_enricher.go deleted file mode 100644 index 4aad08d7..00000000 --- a/internal/controller/profiles/common/status_enricher.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - - "k8s.io/klog/v2" - - "k8s.io/client-go/rest" - - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" -) - -// NewStatusEnricher ... -func NewStatusEnricher(client client.Client, enricher StatusEnricherFn) *StatusEnricher { - return &StatusEnricher{ - C: client, - Enricher: enricher, - } -} - -// StatusEnricherFn is the func that creates the initial reference object, if the object doesn't exist in the cluster, this one is created. -// Can be used as a reference to keep the object immutable -type StatusEnricherFn func(ctx context.Context, client client.Client, workflow *operatorapi.SonataFlow) (client.Object, error) - -// StatusEnricher ... -type StatusEnricher struct { - C client.Client - Config *rest.Config - Enricher StatusEnricherFn -} - -func (d *StatusEnricher) Enrich(ctx context.Context, workflow *operatorapi.SonataFlow) (controllerutil.OperationResult, error) { - result := controllerutil.OperationResultNone - _, err := d.Enricher(ctx, d.C, workflow) - if err != nil { - return result, err - } - - klog.V(log.I).InfoS("Enrichment operation finalized", "result", result, "workflow", workflow.GetName(), "namespace", workflow.GetNamespace()) - return result, nil -} diff --git a/internal/controller/profiles/common/utils.go b/internal/controller/profiles/common/utils.go deleted file mode 100644 index 0fa1ab53..00000000 --- a/internal/controller/profiles/common/utils.go +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - - "k8s.io/client-go/rest" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/utils" -) - -// CleanupOutdatedRevisions helper function to remove the outdated revisions for a workflow deployed with the knative -// deploymentMode. -// TODO: Refactor when we can remove dependency between properties.go -> knative.go, and k8s.go -> knative.go. -func CleanupOutdatedRevisions(ctx context.Context, cfg *rest.Config, workflow *operatorapi.SonataFlow) error { - sfp, err := platform.GetActivePlatform(ctx, utils.GetClient(), workflow.Namespace, false) - if err != nil { - return fmt.Errorf("failed to get active platform to clean workflow outdated revisions, workflow: %s, namespace: %s : %v", workflow.Name, workflow.Namespace, err) - } - if err := knative.CleanupOutdatedRevisions(ctx, cfg, workflow, sfp); err != nil { - return fmt.Errorf("failed to cleanup workflow outdated revisions, workflow: %s, namespace: %s - %v", workflow.Name, workflow.Namespace, err) - } - return nil -} diff --git a/internal/controller/profiles/common/variables/k8s.go b/internal/controller/profiles/common/variables/k8s.go deleted file mode 100644 index b295ab4b..00000000 --- a/internal/controller/profiles/common/variables/k8s.go +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 variables - -import ( - "k8s.io/apimachinery/pkg/util/intstr" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" -) - -var ( - DefaultHTTPWorkflowPortIntStr = intstr.FromInt(constants.DefaultHTTPWorkflowPortInt) -) diff --git a/internal/controller/profiles/dev/object_creators_dev.go b/internal/controller/profiles/dev/object_creators_dev.go deleted file mode 100644 index 3d373d4c..00000000 --- a/internal/controller/profiles/dev/object_creators_dev.go +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "path" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -// serviceCreator is an objectCreator for a basic Service for a workflow using dev profile -// aiming a vanilla Kubernetes Deployment. -// It maps the default HTTP port (80) to the target Java application webserver on port 8080. -// It configures the Service as a NodePort type service, in this way it will be easier for a developer access the service -func serviceCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - object, _ := common.ServiceCreator(workflow) - service := object.(*corev1.Service) - // Let's double-check that the workflow is using the Dev Profile we would like to expose it via NodePort - if profiles.IsDevProfile(workflow) { - service.Spec.Type = corev1.ServiceTypeNodePort - } - return service, nil -} - -func deploymentCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { - - obj, err := common.DeploymentCreator(workflow, plf) - if err != nil { - return nil, err - } - deployment := obj.(*appsv1.Deployment) - _, idx := kubeutil.GetContainerByName(operatorapi.DefaultContainerName, &deployment.Spec.Template.Spec) - healthThreshold := cfg.GetCfg().HealthFailureThresholdDevMode - if workflow.Spec.PodTemplate.Container.StartupProbe == nil { - deployment.Spec.Template.Spec.Containers[idx].StartupProbe.FailureThreshold = healthThreshold - } - if workflow.Spec.PodTemplate.Container.LivenessProbe == nil { - deployment.Spec.Template.Spec.Containers[idx].LivenessProbe.FailureThreshold = healthThreshold - } - if workflow.Spec.PodTemplate.Container.ReadinessProbe == nil { - deployment.Spec.Template.Spec.Containers[idx].ReadinessProbe.FailureThreshold = healthThreshold - } - return deployment, nil -} - -// workflowDefConfigMapCreator creates a new ConfigMap that holds the definition of a workflow specification. -func workflowDefConfigMapCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { - configMap, err := workflowdef.CreateNewConfigMap(workflow) - if err != nil { - return nil, err - } - return configMap, nil -} - -// deploymentMutateVisitor guarantees the state of the default Deployment object -func deploymentMutateVisitor(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) common.MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - if kubeutil.IsObjectNew(object) { - return nil - } - original, err := deploymentCreator(workflow, plf) - if err != nil { - return err - } - return common.EnsureDeployment(original.(*appsv1.Deployment), object.(*appsv1.Deployment)) - } - } -} - -func ensureWorkflowDefConfigMapMutator(workflow *operatorapi.SonataFlow) common.MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - if kubeutil.IsObjectNew(object) { - return nil - } - original, err := workflowDefConfigMapCreator(workflow) - if err != nil { - return err - } - object.(*corev1.ConfigMap).Data = original.(*corev1.ConfigMap).Data - object.(*corev1.ConfigMap).Labels = original.GetLabels() - return nil - } - } -} - -// mountDevConfigMapsMutateVisitor mounts the required configMaps in the Workflow Dev Deployment -func mountDevConfigMapsMutateVisitor(workflow *operatorapi.SonataFlow, flowDefCM, userPropsCM, managedPropsCM *corev1.ConfigMap, workflowResCMs []operatorapi.ConfigMapWorkflowResource) common.MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - deployment := object.(*appsv1.Deployment) - - volumeMounts := []corev1.VolumeMount{ - kubeutil.VolumeMount(configMapResourcesVolumeName, true, quarkusDevConfigMountPath), - } - - // defaultResourcesVolume holds every ConfigMap mount required on src/main/resources - defaultResourcesVolume := corev1.Volume{Name: configMapResourcesVolumeName, VolumeSource: corev1.VolumeSource{Projected: &corev1.ProjectedVolumeSource{}}} - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, userPropsCM.Name, corev1.KeyToPath{Key: workflowproj.ApplicationPropertiesFileName, Path: workflowproj.ApplicationPropertiesFileName}) - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, managedPropsCM.Name, corev1.KeyToPath{Key: workflowproj.GetManagedPropertiesFileName(workflow), Path: workflowproj.GetManagedPropertiesFileName(workflow)}) - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, flowDefCM.Name) - - // resourceVolumes holds every resource that needs to be mounted on src/main/resources/ - resourceVolumes := make([]corev1.Volume, 0) - - for _, workflowResCM := range workflowResCMs { - // if we need to mount at the root dir, we use the defaultResourcesVolume - if len(workflowResCM.WorkflowPath) == 0 { - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, workflowResCM.ConfigMap.Name) - continue - } - // the resource configMap needs a specific dir, inside the src/main/resources - // to avoid clashing with other configMaps trying to mount on the same dir, we create one projected per path - volumeMountName := kubeutil.MustSafeDNS1035(configMapExternalResourcesVolumeNamePrefix, workflowResCM.WorkflowPath) - volumeMounts = kubeutil.VolumeMountAdd(volumeMounts, volumeMountName, path.Join(quarkusDevConfigMountPath, workflowResCM.WorkflowPath)) - resourceVolumes = kubeutil.VolumeAddVolumeProjectionConfigMap(resourceVolumes, workflowResCM.ConfigMap.Name, volumeMountName) - } - - if len(deployment.Spec.Template.Spec.Volumes) == 0 { - deployment.Spec.Template.Spec.Volumes = make([]corev1.Volume, 0, len(resourceVolumes)+1) - } - kubeutil.AddOrReplaceVolume(&deployment.Spec.Template.Spec, defaultResourcesVolume) - kubeutil.AddOrReplaceVolume(&deployment.Spec.Template.Spec, resourceVolumes...) - - _, flowContainerIdx := kubeutil.GetContainerByName(operatorapi.DefaultContainerName, &deployment.Spec.Template.Spec) - if len(deployment.Spec.Template.Spec.Containers[flowContainerIdx].VolumeMounts) == 0 { - deployment.Spec.Template.Spec.Containers[flowContainerIdx].VolumeMounts = make([]corev1.VolumeMount, 0, len(volumeMounts)) - } - kubeutil.AddOrReplaceVolumeMount(&deployment.Spec.Template.Spec.Containers[flowContainerIdx], volumeMounts...) - - return nil - } - } -} diff --git a/internal/controller/profiles/dev/object_creators_dev_test.go b/internal/controller/profiles/dev/object_creators_dev_test.go deleted file mode 100644 index a81ed445..00000000 --- a/internal/controller/profiles/dev/object_creators_dev_test.go +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "testing" - - "github.com/kubesmarts/logic-operator/api/version" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - - "github.com/kubesmarts/logic-operator/test" -) - -func Test_ensureWorkflowDevServiceIsExposed(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - //On Kubernetes we want the service exposed in Dev with NodePort - service, _ := serviceCreator(workflow) - service.SetUID("1") - service.SetResourceVersion("1") - - reflectService := service.(*v1.Service) - - assert.NotNil(t, reflectService) - assert.NotNil(t, reflectService.Spec.Type) - assert.NotEmpty(t, reflectService.Spec.Type) - assert.Equal(t, reflectService.Spec.Type, v1.ServiceTypeNodePort) - assert.NotNil(t, reflectService.ObjectMeta) - assert.NotNil(t, reflectService.ObjectMeta.Labels) - assert.Equal(t, reflectService.ObjectMeta.Labels, map[string]string{ - "app": "greeting", - "app.kubernetes.io/instance": "greeting", - "test": "test", - "sonataflow.org/workflow-app": "greeting", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "greeting", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "app.kubernetes.io/version": version.GetImageTagVersion(), - }) -} diff --git a/internal/controller/profiles/dev/profile_dev.go b/internal/controller/profiles/dev/profile_dev.go deleted file mode 100644 index ab1d7777..00000000 --- a/internal/controller/profiles/dev/profile_dev.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" -) - -var _ profiles.ProfileReconciler = &developmentProfile{} - -type developmentProfile struct { - common.Reconciler -} - -func (d developmentProfile) GetProfile() metadata.ProfileType { - return metadata.DevProfile -} - -func NewProfileReconciler(client client.Client, cfg *rest.Config, recorder record.EventRecorder) profiles.ProfileReconciler { - support := &common.StateSupport{ - C: client, - Cfg: cfg, - Catalog: discovery.NewServiceCatalogForConfig(client, cfg), - Recorder: recorder, - } - - var ensurers *objectEnsurers - var enrichers *statusEnrichers - if utils.IsOpenShift() { - ensurers = newObjectEnsurersOpenShift(support) - enrichers = newStatusEnrichersOpenShift(support) - } else { - ensurers = newObjectEnsurers(support) - enrichers = newStatusEnrichers(support) - } - - stateMachine := common.NewReconciliationStateMachine( - &ensureRunningWorkflowState{StateSupport: support, ensurers: ensurers}, - &followWorkflowDeploymentState{StateSupport: support, enrichers: enrichers}, - &recoverFromFailureState{StateSupport: support}) - - profile := &developmentProfile{ - Reconciler: common.NewReconciler(support, stateMachine), - } - - klog.V(log.I).InfoS("Reconciling in", "profile", profile.GetProfile()) - return profile -} - -func newObjectEnsurers(support *common.StateSupport) *objectEnsurers { - return &objectEnsurers{ - deployment: common.NewObjectEnsurerWithPlatform(support.C, deploymentCreator), - service: common.NewObjectEnsurer(support.C, serviceCreator), - serviceMonitor: common.NewObjectEnsurer(support.C, common.ServiceMonitorCreator), - network: common.NewNoopObjectEnsurer(), - definitionConfigMap: common.NewObjectEnsurer(support.C, workflowDefConfigMapCreator), - userPropsConfigMap: common.NewObjectEnsurer(support.C, common.UserPropsConfigMapCreator), - managedPropsConfigMap: common.NewObjectEnsurerWithPlatform(support.C, common.ManagedPropsConfigMapCreator), - } -} - -func newObjectEnsurersOpenShift(support *common.StateSupport) *objectEnsurers { - return &objectEnsurers{ - deployment: common.NewObjectEnsurerWithPlatform(support.C, deploymentCreator), - service: common.NewObjectEnsurer(support.C, serviceCreator), - serviceMonitor: common.NewObjectEnsurer(support.C, common.ServiceMonitorCreator), - network: common.NewObjectEnsurer(support.C, common.OpenShiftRouteCreator), - definitionConfigMap: common.NewObjectEnsurer(support.C, workflowDefConfigMapCreator), - userPropsConfigMap: common.NewObjectEnsurer(support.C, common.UserPropsConfigMapCreator), - managedPropsConfigMap: common.NewObjectEnsurerWithPlatform(support.C, common.ManagedPropsConfigMapCreator), - } -} - -func newStatusEnrichers(support *common.StateSupport) *statusEnrichers { - return &statusEnrichers{ - networkInfo: common.NewStatusEnricher(support.C, statusEnricher), - } -} - -func newStatusEnrichersOpenShift(support *common.StateSupport) *statusEnrichers { - return &statusEnrichers{ - networkInfo: common.NewStatusEnricher(support.C, statusEnricherOpenShift), - } -} - -type objectEnsurers struct { - deployment common.ObjectEnsurerWithPlatform - service common.ObjectEnsurer - serviceMonitor common.ObjectEnsurer - network common.ObjectEnsurer - definitionConfigMap common.ObjectEnsurer - userPropsConfigMap common.ObjectEnsurer - managedPropsConfigMap common.ObjectEnsurerWithPlatform -} - -type statusEnrichers struct { - networkInfo *common.StatusEnricher - //Here we can add more enrichers if we need in future to enrich objects with more info coming from reconciliation -} diff --git a/internal/controller/profiles/dev/profile_dev_test.go b/internal/controller/profiles/dev/profile_dev_test.go deleted file mode 100644 index 23ef1d90..00000000 --- a/internal/controller/profiles/dev/profile_dev_test.go +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "context" - "sort" - "testing" - - "k8s.io/client-go/rest" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - - corev1 "k8s.io/api/core/v1" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "github.com/kubesmarts/logic-operator/workflowproj" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - "github.com/kubesmarts/logic-operator/utils" - - "github.com/stretchr/testify/assert" - - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" - clientruntime "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - "github.com/kubesmarts/logic-operator/test" -) - -func Test_OverrideStartupProbe(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() - - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // get the deployment, change the probe and reconcile it again - newThreshold := int32(5) //yes we have to force the type for the assertion below - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, cfg.GetCfg().HealthFailureThresholdDevMode, deployment.Spec.Template.Spec.Containers[0].StartupProbe.FailureThreshold) - deployment.Spec.Template.Spec.Containers[0].StartupProbe.FailureThreshold = newThreshold - assert.NoError(t, client.Update(context.TODO(), deployment)) - // reconcile and fetch from the cluster - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - deployment = test.MustGetDeployment(t, client, workflow) - assert.Equal(t, newThreshold, deployment.Spec.Template.Spec.Containers[0].StartupProbe.FailureThreshold) -} - -func Test_recoverFromFailureNoDeployment(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - workflowID := clientruntime.ObjectKeyFromObject(workflow) - - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentFailureReason, "") - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - reconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - // we are in failed state and have no objects - result, err := reconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // the recover state tried to clear the conditions of our workflow, so we can try reconciling it again - workflow = test.MustGetWorkflow(t, client, workflowID) - assert.True(t, workflow.Status.GetTopLevelCondition().IsUnknown()) - result, err = reconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // the deployment should be there - _ = test.MustGetDeployment(t, client, workflow) - - // we failed again, but now we have the deployment - workflow = test.MustGetWorkflow(t, client, workflowID) - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentFailureReason, "") - err = client.Status().Update(context.TODO(), workflow) - assert.NoError(t, err) - // the fake client won't update the deployment status condition since we don't have a deployment controller - // our state will think that we don't have a deployment available yet, so it will try to reset the pods - result, err = reconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - workflow = test.MustGetWorkflow(t, client, workflowID) - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentFailureReason, "") - assert.Equal(t, 1, workflow.Status.RecoverFailureAttempts) - - deployment := test.MustGetDeployment(t, client, workflow) - assert.NotEmpty(t, deployment.Spec.Template.ObjectMeta.Annotations[metadata.RestartedAt]) -} - -func Test_newDevProfile(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - sortVolumeMounts(&deployment.Spec.Template.Spec.Containers[0]) - assert.Equal(t, workflowdef.GetDefaultWorkflowDevModeImageTag(), deployment.Spec.Template.Spec.Containers[0].Image) - assert.NotNil(t, deployment.Spec.Template.Spec.Containers[0].LivenessProbe) - assert.NotNil(t, deployment.Spec.Template.Spec.Containers[0].ReadinessProbe) - assert.NotNil(t, deployment.Spec.Template.Spec.Containers[0].StartupProbe) - - defCM := test.MustGetConfigMap(t, client, workflow) - assert.NotEmpty(t, defCM.Data[workflow.Name+workflowdef.KogitoWorkflowJSONFileExt]) - assert.Equal(t, quarkusDevConfigMountPath, deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath) - assert.Equal(t, "", deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].SubPath) //https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically - - userPropsCM := &corev1.ConfigMap{} - _ = client.Get(context.TODO(), types.NamespacedName{Namespace: workflow.Namespace, Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow)}, userPropsCM) - assert.Empty(t, userPropsCM.Data[workflowproj.ApplicationPropertiesFileName]) - - managedPropsCM := &corev1.ConfigMap{} - _ = client.Get(context.TODO(), types.NamespacedName{Namespace: workflow.Namespace, Name: workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow)}, managedPropsCM) - assert.NotEmpty(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)]) - assert.Equal(t, quarkusDevConfigMountPath, deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath) - assert.Equal(t, "", deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].SubPath) //https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically - assert.Contains(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)], "quarkus.http.port") - - service := test.MustGetService(t, client, workflow) - assert.Equal(t, int32(constants.DefaultHTTPWorkflowPortInt), service.Spec.Ports[0].TargetPort.IntVal) - - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - err = client.Status().Update(context.TODO(), workflow) - assert.NoError(t, err) - - // Mess with the object - service.Spec.Ports[0].TargetPort = intstr.FromInt(9090) - err = client.Update(context.TODO(), service) - assert.NoError(t, err) - - // reconcile again - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the reconciliation ensures the object correctly - service = test.MustGetService(t, client, workflow) - assert.Equal(t, int32(constants.DefaultHTTPWorkflowPortInt), service.Spec.Ports[0].TargetPort.IntVal) - - // now with the deployment - deployment = test.MustGetDeployment(t, client, workflow) - deployment.Spec.Template.Spec.Containers[0].Image = "default" - err = client.Update(context.TODO(), deployment) - assert.NoError(t, err) - - userPropsCM = &corev1.ConfigMap{} - _ = client.Get(context.TODO(), types.NamespacedName{Namespace: workflow.Namespace, Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow)}, userPropsCM) - assert.Empty(t, userPropsCM.Data[workflowproj.ApplicationPropertiesFileName]) - - managedPropsCM = &corev1.ConfigMap{} - _ = client.Get(context.TODO(), types.NamespacedName{Namespace: workflow.Namespace, Name: workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow)}, managedPropsCM) - assert.NotEmpty(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)]) - assert.Contains(t, managedPropsCM.Data[workflowproj.GetManagedPropertiesFileName(workflow)], "quarkus.http.port") - - // reconcile - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - err = client.Status().Update(context.TODO(), workflow) - assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - deployment = test.MustGetDeployment(t, client, workflow) - assert.Equal(t, workflowdef.GetDefaultWorkflowDevModeImageTag(), deployment.Spec.Template.Spec.Containers[0].Image) -} - -func Test_devProfileImageDefaultsNoPlatform(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, workflowdef.GetDefaultWorkflowDevModeImageTag(), deployment.Spec.Template.Spec.Containers[0].Image) -} - -func Test_devProfileWithImageSnapshotOverrideWithPlatform(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - - platform := test.GetBasePlatformWithDevBaseImageInReadyPhase(workflow.Namespace) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, test.CommonImageTag, deployment.Spec.Template.Spec.Containers[0].Image) -} - -func Test_devProfileWithWPlatformWithoutDevBaseImageAndWithBaseImage(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - - platform := test.GetBasePlatformWithBaseImageInReadyPhase(workflow.Namespace) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, workflowdef.GetDefaultWorkflowDevModeImageTag(), deployment.Spec.Template.Spec.Containers[0].Image) -} - -func Test_devProfileWithPlatformWithoutDevBaseImageAndWithoutBaseImage(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - - platform := test.GetBasePlatformInReadyPhase(workflow.Namespace) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, workflowdef.GetDefaultWorkflowDevModeImageTag(), deployment.Spec.Template.Spec.Containers[0].Image) -} - -func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { - configmapName := "mycamel-configmap" - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - workflow.Spec.Resources.ConfigMaps = append(workflow.Spec.Resources.ConfigMaps, - operatorapi.ConfigMapWorkflowResource{ConfigMap: corev1.LocalObjectReference{Name: configmapName}, WorkflowPath: "routes"}) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - camelXmlRouteFileName := "camelroute-xml" - xmlRoute := ` - - - - ` - - camelYamlRouteFileName := "camelroute-yaml" - yamlRoute := `- from: - uri: direct:numberToWords - steps: - - bean: - beanType: java.math.BigInteger - method: valueOf - - setHeader: - name: operationName - constant: NumberToWords - - toD: - uri: cxf://{{com.dataaccess.webservicesserver.url}}?serviceClass=com.dataaccess.webservicesserver.NumberConversionSoapType&wsdlURL=/wsdl/numberconversion.wsdl` - - cmData := make(map[string]string) - cmData[camelXmlRouteFileName] = xmlRoute - cmUser := createConfigMapBase("Test_newDevProfileWithExternalConfigMaps", "mycamel-configmap", cmData) - errCreate := client.Create(context.Background(), cmUser) - assert.Nil(t, errCreate) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - // check if the objects have been created - deployment := test.MustGetDeployment(t, client, workflow) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Containers[0].VolumeMounts)) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Volumes)) - sortVolumeMounts(&deployment.Spec.Template.Spec.Containers[0]) - - wd := deployment.Spec.Template.Spec.Containers[0].VolumeMounts[1] - extCamel := deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0] - assert.Equal(t, configMapResourcesVolumeName, wd.Name) - assert.Equal(t, quarkusDevConfigMountPath, wd.MountPath) - - assert.Equal(t, extCamel.MountPath, quarkusDevConfigMountPath+"/routes") - - cmData[camelYamlRouteFileName] = yamlRoute - errUpdate := client.Update(context.Background(), cmUser) - assert.Nil(t, errUpdate) - - // reconcile again - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - err = client.Update(context.TODO(), workflow) - assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - //Now we expect 4 volumes mount wd, props camelroute.xml and camelroute.yaml - deployment = test.MustGetDeployment(t, client, workflow) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Containers[0].VolumeMounts)) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Volumes)) - sortVolumeMounts(&deployment.Spec.Template.Spec.Containers[0]) - - extCamelRouteOne := deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0] - assert.Equal(t, quarkusDevConfigMountPath+"/routes", extCamelRouteOne.MountPath) - - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - err = client.Update(context.TODO(), workflow) - assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - deployment = test.MustGetDeployment(t, client, workflow) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Containers[0].VolumeMounts)) - assert.Equal(t, 2, len(deployment.Spec.Template.Spec.Volumes)) - - // remove the external configmaps without removing the labels - errDel := client.Delete(context.Background(), cmUser) - assert.Nil(t, errDel) - - // reconcile - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - err = client.Status().Update(context.TODO(), workflow) - assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - assert.Equal(t, api.ExternalResourcesNotFoundReason, workflow.Status.GetTopLevelCondition().Reason) - - // delete the link - workflow.Spec.Resources.ConfigMaps = nil - assert.NoError(t, client.Update(context.TODO(), workflow)) - result, err = devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - deployment = test.MustGetDeployment(t, client, workflow) - assert.Equal(t, 1, len(deployment.Spec.Template.Spec.Volumes)) - assert.Equal(t, 1, len(deployment.Spec.Template.Spec.Containers[0].VolumeMounts)) - sortVolumeMounts(&deployment.Spec.Template.Spec.Containers[0]) - wd = deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0] - assert.Equal(t, wd.Name, configMapResourcesVolumeName) - assert.Equal(t, wd.MountPath, quarkusDevConfigMountPath) -} - -func Test_VolumeWithCapitalizedPaths(t *testing.T) { - configMap := &corev1.ConfigMap{} - test.GetKubernetesResource(test.SonataFlowGreetingsStaticFilesConfig, configMap) - configMap.Namespace = t.Name() - workflow := test.GetSonataFlow(test.SonataFlowGreetingsWithStaticResourcesCR, t.Name()) - - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, configMap).WithStatusSubresource(workflow, configMap).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - - result, err := devReconciler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotNil(t, result) - - deployment := test.MustGetDeployment(t, client, workflow) - assert.NotNil(t, deployment) - - container, _ := kubeutil.GetContainerByName(operatorapi.DefaultContainerName, &deployment.Spec.Template.Spec) - // properties, definitions, and the capitalized value - assert.Len(t, container.VolumeMounts, 2) - assert.Len(t, deployment.Spec.Template.Spec.Volumes, 2) -} - -func sortVolumeMounts(container *corev1.Container) { - sort.SliceStable(container.VolumeMounts, func(i, j int) bool { - return container.VolumeMounts[i].Name < container.VolumeMounts[j].Name - }) -} - -func createConfigMapBase(namespace string, name string, cmData map[string]string) clientruntime.Object { - cm := &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Immutable: utils.Pbool(false), - Data: cmData, - } - return cm -} diff --git a/internal/controller/profiles/dev/states_dev.go b/internal/controller/profiles/dev/states_dev.go deleted file mode 100644 index bb0b2c16..00000000 --- a/internal/controller/profiles/dev/states_dev.go +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "context" - "time" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/util/retry" - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/monitoring" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - "github.com/kubesmarts/logic-operator/log" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -const ( - configMapResourcesVolumeName = "resources" - configMapExternalResourcesVolumeNamePrefix = "res-" - // quarkusDevConfigMountPath mount path for application properties file in the Workflow Quarkus Application - // See: https://quarkus.io/guides/config-reference#application-properties-file - quarkusDevConfigMountPath = "/home/kogito/serverless-workflow-project/src/main/resources" -) - -type ensureRunningWorkflowState struct { - *common.StateSupport - ensurers *objectEnsurers -} - -func (e *ensureRunningWorkflowState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.IsReady() || workflow.Status.GetTopLevelCondition().IsUnknown() || workflow.Status.IsChildObjectsProblem() -} - -func (e *ensureRunningWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - var objs []client.Object - - flowDefCM, _, err := e.ensurers.definitionConfigMap.Ensure(ctx, workflow, ensureWorkflowDefConfigMapMutator(workflow)) - if err != nil { - return ctrl.Result{Requeue: false}, objs, err - } - objs = append(objs, flowDefCM) - - devBaseContainerImage := workflowdef.GetDefaultWorkflowDevModeImageTag() - // check if the Platform available - pl, err := platform.GetActivePlatform(context.TODO(), e.C, workflow.Namespace, true) - if err != nil { - return ctrl.Result{Requeue: false}, objs, err - } - if pl != nil && len(pl.Spec.DevMode.BaseImage) > 0 { - devBaseContainerImage = pl.Spec.DevMode.BaseImage - } - // make the route available before the properties calculation - route, _, err := e.ensurers.network.Ensure(ctx, workflow) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - objs = append(objs, route) - - userPropsCM, _, err := e.ensurers.userPropsConfigMap.Ensure(ctx, workflow) - if err != nil { - return ctrl.Result{Requeue: false}, objs, err - } - managedPropsCM, _, err := e.ensurers.managedPropsConfigMap.Ensure(ctx, workflow, pl, common.ManagedPropertiesMutateVisitor(ctx, e.Catalog, workflow, pl, userPropsCM.(*corev1.ConfigMap))) - if err != nil { - return ctrl.Result{Requeue: false}, objs, err - } - objs = append(objs, managedPropsCM) - - externalCM, err := workflowdef.FetchExternalResourcesConfigMapsRef(e.C, workflow) - if err != nil { - workflow.Status.Manager().MarkFalsef(api.RunningConditionType, api.ExternalResourcesNotFoundReason, "External Resources ConfigMap not found: %s", err.Error()) - if _, err = e.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, nil - } - - deployment, _, err := e.ensurers.deployment.Ensure(ctx, workflow, pl, - deploymentMutateVisitor(workflow, pl), - common.ImageDeploymentMutateVisitor(workflow, devBaseContainerImage), - mountDevConfigMapsMutateVisitor(workflow, flowDefCM.(*corev1.ConfigMap), userPropsCM.(*corev1.ConfigMap), managedPropsCM.(*corev1.ConfigMap), externalCM)) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - objs = append(objs, deployment) - - service, _, err := e.ensurers.service.Ensure(ctx, workflow, common.ServiceMutateVisitor(workflow)) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - objs = append(objs, service) - - serviceMonitor, err := e.ensureServiceMonitor(ctx, workflow, pl) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - if serviceMonitor != nil { - objs = append(objs, serviceMonitor) - } - - // First time reconciling this object, mark as wait for deployment - if workflow.Status.GetTopLevelCondition().IsUnknown() { - klog.V(log.I).InfoS("Workflow is in WaitingForDeployment Condition") - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForDeploymentReason, "") - if _, err = e.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - return ctrl.Result{RequeueAfter: constants.RequeueAfterIsRunning}, objs, nil - } - - // Is the deployment still available? - convertedDeployment := deployment.(*appsv1.Deployment) - if !kubeutil.IsDeploymentAvailable(convertedDeployment) { - klog.V(log.I).InfoS("Workflow is not running due to a problem in the Deployment. Attempt to recover.") - workflow.Status.Manager().MarkFalse(api.RunningConditionType, - api.DeploymentUnavailableReason, - common.GetDeploymentUnavailabilityMessage(convertedDeployment)) - if _, err = e.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err - } - } - - return ctrl.Result{RequeueAfter: constants.RequeueAfterIsRunning}, objs, nil -} - -func (e *ensureRunningWorkflowState) ensureServiceMonitor(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform) (client.Object, error) { - if monitoring.IsMonitoringEnabled(pl) { - serviceMonitor, _, err := e.ensurers.serviceMonitor.Ensure(ctx, workflow) - return serviceMonitor, err - } - return nil, nil -} - -func (e *ensureRunningWorkflowState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - //By default, we don't want to perform anything after the reconciliation, and so we will simply return no error - return nil -} - -type followWorkflowDeploymentState struct { - *common.StateSupport - enrichers *statusEnrichers -} - -func (f *followWorkflowDeploymentState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.IsWaitingForDeployment() -} - -func (f *followWorkflowDeploymentState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - result, err := common.DeploymentManager(f.C).SyncDeploymentStatus(ctx, workflow) - if err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err - } - - if _, err := f.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err - } - - return result, nil, nil -} - -func (f *followWorkflowDeploymentState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - deployment := &appsv1.Deployment{} - if err := f.C.Get(ctx, client.ObjectKeyFromObject(workflow), deployment); err != nil { - return err - } - if deployment != nil && kubeutil.IsDeploymentAvailable(deployment) { - // Enriching Workflow CR status with needed network info - if _, err := f.enrichers.networkInfo.Enrich(ctx, workflow); err != nil { - return err - } - if _, err := f.PerformStatusUpdate(ctx, workflow); err != nil { - return err - } - } - return nil -} - -type recoverFromFailureState struct { - *common.StateSupport -} - -func (r *recoverFromFailureState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.GetCondition(api.RunningConditionType).IsFalse() -} - -func (r *recoverFromFailureState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - // for now, a very basic attempt to recover by rolling out the deployment - deployment := &appsv1.Deployment{} - if err := r.C.Get(ctx, client.ObjectKeyFromObject(workflow), deployment); err != nil { - // if the deployment is not there, let's try to reset the status condition and make the reconciliation fix the objects - if errors.IsNotFound(err) { - klog.V(log.I).InfoS("Tried to recover from failed state, no deployment found, trying to reset the workflow conditions") - workflow.Status.RecoverFailureAttempts = 0 - workflow.Status.Manager().MarkUnknown(api.RunningConditionType, "", "") - if _, updateErr := r.PerformStatusUpdate(ctx, workflow); updateErr != nil { - return ctrl.Result{Requeue: false}, nil, updateErr - } - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, nil - } - return ctrl.Result{Requeue: false}, nil, err - } - - // if the deployment is progressing we might have good news - if kubeutil.IsDeploymentAvailable(deployment) { - workflow.Status.RecoverFailureAttempts = 0 - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - if _, updateErr := r.PerformStatusUpdate(ctx, workflow); updateErr != nil { - return ctrl.Result{Requeue: false}, nil, updateErr - } - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, nil - } - - if workflow.Status.RecoverFailureAttempts >= constants.RecoverDeploymentErrorRetries { - workflow.Status.Manager().MarkFalsef(api.RunningConditionType, api.RedeploymentExhaustedReason, - "Can't recover workflow from failure after maximum attempts: %d", workflow.Status.RecoverFailureAttempts) - if _, updateErr := r.PerformStatusUpdate(ctx, workflow); updateErr != nil { - return ctrl.Result{}, nil, updateErr - } - return ctrl.Result{RequeueAfter: constants.RequeueRecoverDeploymentErrorInterval}, nil, nil - } - - // TODO: we can improve deployment failures https://issues.redhat.com/browse/KOGITO-8812 - - // Guard to avoid consecutive reconciliations to mess with the recover interval - if !workflow.Status.LastTimeRecoverAttempt.IsZero() && - metav1.Now().Sub(workflow.Status.LastTimeRecoverAttempt.Time).Minutes() > 10 { - return ctrl.Result{RequeueAfter: time.Minute * constants.RecoverDeploymentErrorInterval}, nil, nil - } - - // let's try rolling out the deployment - if err := kubeutil.MarkDeploymentToRollout(deployment); err != nil { - return ctrl.Result{}, nil, err - } - retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { - updateErr := r.C.Update(ctx, deployment) - return updateErr - }) - - if retryErr != nil { - klog.V(log.E).ErrorS(retryErr, "Error during Deployment rollout") - return ctrl.Result{RequeueAfter: constants.RequeueRecoverDeploymentErrorInterval}, nil, nil - } - - workflow.Status.RecoverFailureAttempts += 1 - workflow.Status.LastTimeRecoverAttempt = metav1.Now() - if _, err := r.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{Requeue: false}, nil, err - } - return ctrl.Result{RequeueAfter: constants.RequeueRecoverDeploymentErrorInterval}, nil, nil -} - -func (r *recoverFromFailureState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - //By default, we don't want to perform anything after the reconciliation, and so we will simply return no error - return nil -} diff --git a/internal/controller/profiles/dev/status_enricher_dev.go b/internal/controller/profiles/dev/status_enricher_dev.go deleted file mode 100644 index 42c4c305..00000000 --- a/internal/controller/profiles/dev/status_enricher_dev.go +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "context" - "fmt" - - "github.com/kubesmarts/logic-operator/api/metadata" - - openshiftv1 "github.com/openshift/api/route/v1" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -func statusEnricher(ctx context.Context, c client.Client, workflow *operatorapi.SonataFlow) (client.Object, error) { - //If the workflow Status hasn't got a NodePort Endpoint, we are ensuring it will be set - // If we aren't on OpenShift we will enrich the status with 2 info: - // - Address the service can be reached - // - Node port used - service := &v1.Service{} - - err := c.Get(ctx, types.NamespacedName{Namespace: workflow.Namespace, Name: workflow.Name}, service) - if err != nil { - return nil, err - } - - //If the service has got a Port that is a nodePort we have to use it to create the workflow's NodePort Endpoint - if service.Spec.Ports != nil && len(service.Spec.Ports) > 0 { - if port := findNodePortFromPorts(service.Spec.Ports); port > 0 { - labels := workflowproj.GetDefaultLabels(workflow) - - podList := &v1.PodList{} - opts := []client.ListOption{ - client.InNamespace(workflow.Namespace), - client.MatchingLabels{metadata.KubernetesLabelName: labels[metadata.KubernetesLabelName]}, - } - err := c.List(ctx, podList, opts...) - if err != nil { - return nil, err - } - var ipaddr string - for _, p := range podList.Items { - ipaddr = p.Status.HostIP - break - } - - url, err := apis.ParseURL("http://" + ipaddr + ":" + fmt.Sprint(port) + "/" + workflow.Name) - if err != nil { - return nil, err - } - workflow.Status.Endpoint = url - } - - address, err := kubernetes.RetrieveServiceURL(service) - if err != nil { - return nil, err - } - workflow.Status.Address = duckv1.Addressable{ - URL: address, - } - } - - return workflow, nil -} - -// findNodePortFromPorts returns the first Port in an array of ServicePort -func findNodePortFromPorts(ports []v1.ServicePort) int { - if len(ports) > 0 { - for _, p := range ports { - if p.NodePort != 0 { - return int(p.NodePort) - } - } - } - //If we are not able to find a NodePort let's return the zero value - return 0 -} - -func statusEnricherOpenShift(ctx context.Context, client client.Client, workflow *operatorapi.SonataFlow) (client.Object, error) { - // On OpenShift we need to retrieve the Route to have the URL the service is available to - route := &openshiftv1.Route{} - err := client.Get(ctx, types.NamespacedName{Namespace: workflow.Namespace, Name: workflow.Name}, route) - if err != nil { - return nil, err - } - var url *apis.URL - if route.Spec.TLS != nil { - url = apis.HTTPS(route.Spec.Host) - } else { - url = apis.HTTP(route.Spec.Host) - } - url.Path = workflow.Name - - workflow.Status.Endpoint = url - - if err != nil { - return nil, err - } - workflow.Status.Address = duckv1.Addressable{ - URL: url, - } - return workflow, nil -} diff --git a/internal/controller/profiles/dev/status_enricher_dev_test.go b/internal/controller/profiles/dev/status_enricher_dev_test.go deleted file mode 100644 index c2fe45a8..00000000 --- a/internal/controller/profiles/dev/status_enricher_dev_test.go +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 dev - -import ( - "context" - "strings" - "testing" - - openshiftv1 "github.com/openshift/api/route/v1" - "github.com/stretchr/testify/assert" - "knative.dev/pkg/apis" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - - apiv08 "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test" -) - -func Test_enrichmentStatusOnK8s(t *testing.T) { - t.Run("verify that the service URL is returned with the default cluster name on default namespace", func(t *testing.T) { - - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - workflow.Namespace = toK8SNamespace(t.Name()) - service, _ := common.ServiceCreator(workflow) - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, service).Build() - obj, err := statusEnricher(context.TODO(), client, workflow) - - reflectWorkflow := obj.(*apiv08.SonataFlow) - assert.NoError(t, err) - assert.NotNil(t, obj) - assert.NotNil(t, reflectWorkflow.Status.Address) - assert.Equal(t, reflectWorkflow.Status.Address.URL.String(), "http://"+workflow.Name+"."+workflow.Namespace+".svc.cluster.local/"+workflow.Name) - - }) - - t.Run("verify that the service URL won't be generated if an invalid namespace is used", func(t *testing.T) { - - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - workflow.Namespace = t.Name() - service, _ := serviceCreator(workflow) - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, service).Build() - _, err := statusEnricher(context.TODO(), client, workflow) - assert.Error(t, err) - - }) -} - -func Test_enrichmentStatusOnOCP(t *testing.T) { - t.Run("verify that the service URL is returned with the default cluster name on default namespace", func(t *testing.T) { - workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) - workflow.Namespace = toK8SNamespace(t.Name()) - service, _ := serviceCreator(workflow) - route := &openshiftv1.Route{} - route.Name = workflow.Name - route.Namespace = workflow.Namespace - route.Spec.Host = workflow.Name + "." + workflow.Namespace + ".apps-crc.testing" - client := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(workflow, service, route).Build() - obj, err := statusEnricherOpenShift(context.TODO(), client, workflow) - - reflectWorkflow := obj.(*apiv08.SonataFlow) - assert.NoError(t, err) - assert.NotNil(t, obj) - assert.NotNil(t, reflectWorkflow.Status.Address) - expectedURL := apis.HTTP(route.Spec.Host) - expectedURL.Path = workflow.Name - assert.Equal(t, reflectWorkflow.Status.Address.URL.String(), expectedURL.String()) - - }) -} - -func toK8SNamespace(testName string) string { - return strings.ToLower(strings.Replace(strings.Split(testName, "/")[0], "_", "-", 1)) -} diff --git a/internal/controller/profiles/factory/factory.go b/internal/controller/profiles/factory/factory.go deleted file mode 100644 index 3d871693..00000000 --- a/internal/controller/profiles/factory/factory.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 factory - -import ( - "github.com/kubesmarts/logic-operator/internal/controller/profiles/gitops" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/preview" - "github.com/kubesmarts/logic-operator/log" - - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/dev" -) - -type reconcilerBuilder func(client client.Client, cfg *rest.Config, recorder record.EventRecorder) profiles.ProfileReconciler - -var profileBuilders = map[metadata.ProfileType]reconcilerBuilder{ - metadata.PreviewProfile: preview.NewProfileReconciler, - metadata.DevProfile: dev.NewProfileReconciler, - metadata.GitOpsProfile: gitops.NewProfileForOpsReconciler, -} - -func profileBuilder(workflow *operatorapi.SonataFlow) reconcilerBuilder { - profile := metadata.GetProfileOrDefault(workflow.Annotations) - // keep backward compatibility - if profile == metadata.ProdProfile { - klog.V(log.W).Infof("Profile %s is deprecated, please use '%s' instead.", metadata.ProdProfile, metadata.PreviewProfile) - profile = metadata.PreviewProfile - } - // Enforce GitOps profile if the .spec.podTemplate.container.image is set in the Preview profile. - if (profile == metadata.PreviewProfile || profile == metadata.ProdProfile) && workflow.HasContainerSpecImage() { - workflow.Annotations[metadata.Profile] = metadata.GitOpsProfile.String() - return profileBuilders[metadata.GitOpsProfile] - } - if _, ok := profileBuilders[profile]; !ok { - klog.V(log.W).Infof("Profile %s not supported, please use '%s' or '%s'. Falling back to %s", profile, metadata.PreviewProfile, metadata.DevProfile, metadata.DefaultProfile) - return profileBuilders[metadata.DefaultProfile] - } - return profileBuilders[profile] -} - -// NewReconciler creates a new ProfileReconciler based on the given workflow and context. -func NewReconciler(client client.Client, cfg *rest.Config, recorder record.EventRecorder, workflow *operatorapi.SonataFlow) profiles.ProfileReconciler { - return profileBuilder(workflow)(client, cfg, recorder) -} diff --git a/internal/controller/profiles/gitops/alias.go b/internal/controller/profiles/gitops/alias.go deleted file mode 100644 index 7f6d64bc..00000000 --- a/internal/controller/profiles/gitops/alias.go +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 gitops - -import "github.com/kubesmarts/logic-operator/internal/controller/profiles/preview" - -// Aliases to preview profile package to avoid cluttering this package with references to preview profile. -// It makes easier to maintain and understand where it comes the references. - -var newDeploymentReconciler = preview.NewDeploymentReconciler -var newObjectEnsurers = preview.NewObjectEnsurers - -type objectEnsurers = preview.ObjectEnsurers diff --git a/internal/controller/profiles/gitops/profile_gitops.go b/internal/controller/profiles/gitops/profile_gitops.go deleted file mode 100644 index fdf95211..00000000 --- a/internal/controller/profiles/gitops/profile_gitops.go +++ /dev/null @@ -1,60 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 gitops - -import ( - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" -) - -var _ profiles.ProfileReconciler = &gitOpsProfile{} - -type gitOpsProfile struct { - common.Reconciler -} - -// NewProfileForOpsReconciler creates an alternative prod profile that won't require to build the workflow image in order to deploy -// the workflow application. It assumes that the image has been built somewhere else. -func NewProfileForOpsReconciler(client client.Client, cfg *rest.Config, recorder record.EventRecorder) profiles.ProfileReconciler { - support := &common.StateSupport{ - C: client, - Cfg: cfg, - Catalog: discovery.NewServiceCatalogForConfig(client, cfg), - Recorder: recorder, - } - // the reconciliation state machine - stateMachine := common.NewReconciliationStateMachine( - &ensureBuildSkipped{StateSupport: support}, - &followDeployWorkflowState{StateSupport: support, ensurers: newObjectEnsurers(support)}, - ) - reconciler := &gitOpsProfile{ - Reconciler: common.NewReconciler(support, stateMachine), - } - - return reconciler -} - -func (p gitOpsProfile) GetProfile() metadata.ProfileType { - return metadata.GitOpsProfile -} diff --git a/internal/controller/profiles/gitops/profile_gitops_test.go b/internal/controller/profiles/gitops/profile_gitops_test.go deleted file mode 100644 index c79f94c1..00000000 --- a/internal/controller/profiles/gitops/profile_gitops_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 gitops - -import ( - "context" - "testing" - - "github.com/kubesmarts/logic-operator/api/version" - - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/rest" - clientruntime "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/utils" -) - -func Test_Reconciler_ProdOps(t *testing.T) { - workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name()) - workflow.Spec.PodTemplate.PodSpec.InitContainers = append(workflow.Spec.PodTemplate.PodSpec.InitContainers, corev1.Container{ - Name: "check-postgres", - Image: "registry.access.redhat.com/ubi9/ubi-micro:latest", - Command: []string{"sh", "-c", "until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo \"Waiting for postgres server\"; sleep 3; done;"}, - }) - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow). - WithStatusSubresource(workflow, &operatorapi.SonataFlowBuild{}).Build() - - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - - result, err := NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - - assert.NotNil(t, result.RequeueAfter) - assert.True(t, workflow.Status.GetCondition(api.BuiltConditionType).IsFalse()) - assert.Equal(t, api.BuildSkippedReason, workflow.Status.GetCondition(api.BuiltConditionType).Reason) - // We need the deployment controller to tell us that the workflow is ready - // Since we don't have it in a mocked env, the result must be ready == false - assert.False(t, workflow.Status.IsReady()) - - // Reconcile again to run the deployment handler - result, err = NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - - // Let's check for the right creation of the workflow (one CM volume, one container with a custom image) - deployment := &appsv1.Deployment{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), deployment) - assert.NoError(t, err) - - assert.Len(t, deployment.Spec.Template.Spec.Volumes, 1) - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - assert.Len(t, deployment.Spec.Template.Spec.InitContainers, 1) - assert.Len(t, deployment.Spec.Template.Spec.Containers[0].VolumeMounts, 1) - - assert.NotNil(t, deployment.ObjectMeta) - assert.NotNil(t, deployment.ObjectMeta.Labels) - assert.Equal(t, deployment.ObjectMeta.Labels, map[string]string{ - "app": "simple", - "app.kubernetes.io/instance": "simple", - "test": "test", - "sonataflow.org/workflow-app": "simple", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "simple", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "app.kubernetes.io/part-of": "sonataflow-platform", - "app.kubernetes.io/version": version.GetImageTagVersion(), - }) -} diff --git a/internal/controller/profiles/gitops/states_gitops.go b/internal/controller/profiles/gitops/states_gitops.go deleted file mode 100644 index 7ce65faa..00000000 --- a/internal/controller/profiles/gitops/states_gitops.go +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 gitops - -import ( - "context" - - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" -) - -type ensureBuildSkipped struct { - *common.StateSupport -} - -func (f *ensureBuildSkipped) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.GetCondition(api.BuiltConditionType).IsUnknown() || - workflow.Status.GetCondition(api.BuiltConditionType).IsTrue() || - workflow.Status.GetCondition(api.BuiltConditionType).Reason != api.BuildSkippedReason -} - -func (f *ensureBuildSkipped) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - // We skip the build, so let's ensure the status reflect that - workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildSkippedReason, "") - if _, err := f.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{Requeue: false}, nil, err - } - - return ctrl.Result{Requeue: true}, nil, nil -} - -func (f *ensureBuildSkipped) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - //By default, we don't want to perform anything after the reconciliation, and so we will simply return no error - return nil -} - -type followDeployWorkflowState struct { - *common.StateSupport - ensurers *objectEnsurers -} - -func (f *followDeployWorkflowState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - // we always reconcile since in this flow we don't mind building anything, just reconcile the deployment state - return workflow.Status.GetCondition(api.BuiltConditionType).Reason == api.BuildSkippedReason -} - -func (f *followDeployWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - return newDeploymentReconciler(f.StateSupport, f.ensurers).Reconcile(ctx, workflow) -} - -func (f *followDeployWorkflowState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - // Clean up the outdated Knative revisions, if any - return common.CleanupOutdatedRevisions(ctx, f.Cfg, workflow) -} diff --git a/internal/controller/profiles/monitoring/monitoring.go b/internal/controller/profiles/monitoring/monitoring.go deleted file mode 100644 index d537ec94..00000000 --- a/internal/controller/profiles/monitoring/monitoring.go +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 monitoring - -import ( - "context" - - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/monitoring" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/log" -) - -var _ MonitoringEventingHandler = &monitoringObjectManager{} - -type monitoringObjectManager struct { - serviceMonitor common.ObjectEnsurer - *common.StateSupport -} - -func NewMonitoringHandler(support *common.StateSupport) MonitoringEventingHandler { - return &monitoringObjectManager{ - serviceMonitor: common.NewObjectEnsurer(support.C, common.ServiceMonitorCreator), - StateSupport: support, - } -} - -type MonitoringEventingHandler interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) ([]client.Object, error) -} - -func (k monitoringObjectManager) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) ([]client.Object, error) { - var objs []client.Object - monitoringAvail, err := monitoring.GetPrometheusAvailability(k.Cfg) - if err != nil { - klog.V(log.I).InfoS("Error checking Prometheus availability: %v", err) - return nil, err - } - if monitoringAvail { - // create serviceMonitor - serviceMonitor, _, err := k.serviceMonitor.Ensure(ctx, workflow) - if err != nil { - return objs, err - } else if serviceMonitor != nil { - objs = append(objs, serviceMonitor) - } - } - return objs, nil -} diff --git a/internal/controller/profiles/preview/deployment_handler.go b/internal/controller/profiles/preview/deployment_handler.go deleted file mode 100644 index e26f125b..00000000 --- a/internal/controller/profiles/preview/deployment_handler.go +++ /dev/null @@ -1,280 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 preview - -import ( - "context" - "fmt" - - "github.com/kubesmarts/logic-operator/internal/manager" - - "github.com/kubesmarts/logic-operator/internal/controller/eventing" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - - "k8s.io/client-go/util/retry" - - "k8s.io/apimachinery/pkg/types" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/properties" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - "github.com/kubesmarts/logic-operator/log" - - v1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/internal/controller/knative" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/monitoring" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/utils" -) - -type DeploymentReconciler struct { - *common.StateSupport - ensurers *ObjectEnsurers -} - -func NewDeploymentReconciler(stateSupport *common.StateSupport, ensurer *ObjectEnsurers) *DeploymentReconciler { - return &DeploymentReconciler{ - StateSupport: stateSupport, - ensurers: ensurer, - } -} - -func (d *DeploymentReconciler) Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (reconcile.Result, []client.Object, error) { - return d.reconcileWithImage(ctx, workflow, "") -} - -func (d *DeploymentReconciler) reconcileWithImage(ctx context.Context, workflow *operatorapi.SonataFlow, image string) (reconcile.Result, []client.Object, error) { - // Checks if we need Knative installed and is not present. - if requires, err := d.ensureKnativeServingRequired(workflow); requires || err != nil { - return reconcile.Result{Requeue: false}, nil, err - } - - previousStatus := workflow.Status - // Ensure objects - result, objs, err := d.ensureObjects(ctx, workflow, image) - if err != nil || result.Requeue { - return result, objs, err - } - - // Follow deployment status - result, err = common.DeploymentManager(d.C).SyncDeploymentStatus(ctx, workflow) - if err != nil { - return reconcile.Result{Requeue: false}, nil, err - } - - d.updateLastTimeStatusNotified(workflow, previousStatus) - if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil { - return reconcile.Result{Requeue: false}, nil, err - } - d.scheduleWorkflowStatusChangeNotification(ctx, workflow) - return result, objs, nil -} - -// ensureKnativeServingRequired returns true if the SonataFlow instance requires Knative deployment and Knative Serving is not available. -func (d *DeploymentReconciler) ensureKnativeServingRequired(workflow *operatorapi.SonataFlow) (bool, error) { - if workflow.IsKnativeDeployment() { - avail, err := knative.GetKnativeAvailability(d.Cfg) - if err != nil { - return true, err - } - if !avail.Serving { - d.Recorder.Eventf(workflow, v1.EventTypeWarning, - "KnativeServingNotAvailable", - "Knative Serving is not available in this cluster, can't deploy workflow. Please update the deployment model to %s", - operatorapi.KubernetesDeploymentModel) - return true, nil - } - } - return false, nil -} - -func (d *DeploymentReconciler) ensureObjects(ctx context.Context, workflow *operatorapi.SonataFlow, image string) (reconcile.Result, []client.Object, error) { - pl, _ := platform.GetActivePlatform(ctx, d.C, workflow.Namespace, true) - userPropsCM, _, err := d.ensurers.userPropsConfigMap.Ensure(ctx, workflow) - if err != nil { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.ExternalResourcesNotFoundReason, "Unable to retrieve the user properties config map") - _, _ = d.PerformStatusUpdate(ctx, workflow) - return reconcile.Result{}, nil, err - } - managedPropsCM, _, err := d.ensurers.managedPropsConfigMap.Ensure(ctx, workflow, pl, - common.ManagedPropertiesMutateVisitor(ctx, d.StateSupport.Catalog, workflow, pl, userPropsCM.(*v1.ConfigMap))) - if err != nil { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.ExternalResourcesNotFoundReason, "Unable to retrieve the managed properties config map") - _, _ = d.PerformStatusUpdate(ctx, workflow) - return reconcile.Result{}, nil, err - } - - deployment, deploymentOp, err := - d.ensurers.DeploymentByDeploymentModel(workflow).Ensure(ctx, workflow, pl, - d.deploymentModelMutateVisitors(workflow, pl, image, userPropsCM.(*v1.ConfigMap), managedPropsCM.(*v1.ConfigMap))...) - if err != nil { - workflow.Status.Manager().MarkFalsef(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to perform the deploy due to: %v ", err) - _, _ = d.PerformStatusUpdate(ctx, workflow) - return reconcile.Result{}, nil, err - } - - service, _, err := d.ensurers.ServiceByDeploymentModel(workflow).Ensure(ctx, workflow, common.ServiceMutateVisitor(workflow)) - if err != nil { - workflow.Status.Manager().MarkFalsef(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to make the service available due to: %v ", err) - _, _ = d.PerformStatusUpdate(ctx, workflow) - return reconcile.Result{}, nil, err - } - - objs := []client.Object{deployment, managedPropsCM, service} - - podDisruptionBudget, err := NewPodDisruptionBudgetHandler(d.StateSupport).Ensure(ctx, workflow) - if err != nil { - return reconcile.Result{}, nil, err - } - if podDisruptionBudget != nil { - objs = append(objs, podDisruptionBudget) - } - - eventingObjs, err := common.NewKnativeEventingHandler(d.StateSupport, pl).Ensure(ctx, workflow) - if err != nil { - return reconcile.Result{}, nil, err - } - objs = append(objs, eventingObjs...) - - serviceMonitor, err := d.ensureServiceMonitor(ctx, workflow, pl) - if err != nil { - return reconcile.Result{}, nil, err - } - if serviceMonitor != nil { - objs = append(objs, serviceMonitor) - } - - if deploymentOp == controllerutil.OperationResultCreated { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForDeploymentReason, "") - if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil { - return reconcile.Result{}, nil, err - } - return reconcile.Result{RequeueAfter: constants.RequeueAfterFollowDeployment, Requeue: true}, objs, nil - } - return reconcile.Result{}, objs, nil -} - -func (d *DeploymentReconciler) ensureServiceMonitor(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform) (client.Object, error) { - if monitoring.IsMonitoringEnabled(pl) { - serviceMonitor, _, err := d.ensurers.ServiceMonitorByDeploymentModel(workflow).Ensure(ctx, workflow) - return serviceMonitor, err - } - return nil, nil -} - -func (d *DeploymentReconciler) deploymentModelMutateVisitors( - workflow *operatorapi.SonataFlow, - plf *operatorapi.SonataFlowPlatform, - image string, - userPropsCM *v1.ConfigMap, - managedPropsCM *v1.ConfigMap) []common.MutateVisitor { - - if workflow.IsKnativeDeployment() { - return []common.MutateVisitor{common.KServiceMutateVisitor(workflow, plf), - common.ImageKServiceMutateVisitor(workflow, image), - mountConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), - common.RestoreKServiceVolumeAndVolumeMountMutateVisitor(), - } - } - - if utils.IsOpenShift() { - return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf), - mountConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), - addOpenShiftImageTriggerDeploymentMutateVisitor(workflow, image), - common.ImageDeploymentMutateVisitor(workflow, image), - common.RestoreDeploymentVolumeAndVolumeMountMutateVisitor(), - common.RolloutDeploymentIfCMChangedMutateVisitor(workflow, userPropsCM, managedPropsCM), - } - } - return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf), - common.ImageDeploymentMutateVisitor(workflow, image), - mountConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), - common.RestoreDeploymentVolumeAndVolumeMountMutateVisitor(), - common.RolloutDeploymentIfCMChangedMutateVisitor(workflow, userPropsCM, managedPropsCM)} -} - -func (d *DeploymentReconciler) updateLastTimeStatusNotified(workflow *operatorapi.SonataFlow, previousStatus operatorapi.SonataFlowStatus) { - previousRunningCondition := previousStatus.GetCondition(api.RunningConditionType) - currentRunningCondition := workflow.Status.GetCondition(api.RunningConditionType) - - if previousRunningCondition == nil { - previousRunningCondition = currentRunningCondition - } - if previousRunningCondition.Status != currentRunningCondition.Status || workflow.Status.LastTimeStatusNotified != nil && workflow.Status.LastTimeStatusNotified.Time.Before(manager.GetOperatorStartTime()) { - workflow.Status.LastTimeStatusNotified = nil - } -} - -func (d *DeploymentReconciler) scheduleWorkflowStatusChangeNotification(ctx context.Context, workflow *operatorapi.SonataFlow) { - if workflow.Status.LastTimeStatusNotified == nil { - manager.GetSFCWorker().RunAsync(func() { - if err := notifyWorkflowStatusChange(d.C, workflow.Name, workflow.Namespace); err != nil { - klog.V(log.E).ErrorS(err, "Failed to notify workflow status change, controller will schedule a new retry.", "workflow", "namespace", workflow.Name, workflow.Namespace, err) - } - }) - } -} - -func notifyWorkflowStatusChange(cli client.Client, wfName, wfNamespace string) error { - retryErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - var err error - var uri string - workflow := &operatorapi.SonataFlow{} - if err = cli.Get(context.Background(), types.NamespacedName{Name: wfName, Namespace: wfNamespace}, workflow); err != nil { - return err - } - available := workflow.Status.GetCondition(api.RunningConditionType).IsTrue() - if uri, err = eventing.GetWorkflowDefinitionEventsTargetURL(cli, workflow); err != nil { - return fmt.Errorf("failed to get workflow definition events target url to send the workflow definition status update event: %v", err) - } - if len(uri) == 0 { - klog.V(log.D).Infof("No enabled DataIndex, nor Broker, nor Sink configuration was found to send the workflow definition status update event for workflow: %s, namespace: %s", workflow.Name, workflow.Namespace) - return nil - } - - ctx, cancel := context.WithTimeout(context.Background(), constants.EventDeliveryTimeout) - defer cancel() - evt := workflowdef.NewWorkflowDefinitionAvailabilityEvent(workflow, workflowdef.SonataFlowOperatorSource, properties.GetWorkflowEndpointUrl(workflow), available) - if err = utils.SendCloudEventWithContext(evt, ctx, uri); err != nil { - return fmt.Errorf("failed to send workflow definition status update event: %v", err) - // Controller handle to program a new notification based on the LastTimeStatusNotified. - } else { - now := metav1.Now() - // Register the LastTimeStatusNotified, the controller knows how to react based on that value. - workflow.Status.LastTimeStatusNotified = &now - if err = cli.Status().Update(context.Background(), workflow); err != nil { - return err - } - } - return nil - }) - return retryErr -} diff --git a/internal/controller/profiles/preview/deployment_handler_test.go b/internal/controller/profiles/preview/deployment_handler_test.go deleted file mode 100644 index c2e581ca..00000000 --- a/internal/controller/profiles/preview/deployment_handler_test.go +++ /dev/null @@ -1,231 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 preview - -import ( - "context" - "testing" - - "github.com/kubesmarts/logic-operator/internal/manager" - - "github.com/magiconair/properties" - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/utils" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -type fakeDeploymentReconciler struct { - DeploymentReconciler -} - -func Test_CheckDeploymentModelIsKnative(t *testing.T) { - workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name()) - workflow.Spec.PodTemplate.DeploymentModel = v1alpha08.KnativeDeploymentModel - - cli := test.NewSonataFlowClientBuilderWithKnative(). - WithRuntimeObjects(workflow). - WithStatusSubresource(workflow). - Build() - stateSupport := fakeReconcilerSupport(cli) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := NewDeploymentReconciler(stateSupport, NewObjectEnsurers(stateSupport)) - - result, objects, err := handler.ensureObjects(context.TODO(), workflow, "") - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - - var ksvc *servingv1.Service - for _, o := range objects { - if _, ok := o.(*servingv1.Service); ok { - ksvc = o.(*servingv1.Service) - assert.Equal(t, v1alpha08.DefaultContainerName, ksvc.Spec.Template.Spec.Containers[0].Name) - break - } - } - assert.NotNil(t, ksvc) -} - -func Test_CheckPodTemplateChangesReflectDeployment(t *testing.T) { - manager.InitializeSFCWorker(manager.SonataFlowControllerWorkerSize) - manager.SetOperatorStartTime() - workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name()) - - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow). - WithStatusSubresource(workflow). - Build() - stateSupport := fakeReconcilerSupport(client) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := NewDeploymentReconciler(stateSupport, NewObjectEnsurers(stateSupport)) - - result, objects, err := handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - - // Second reconciliation, we do change the image and that must reflect the deployment - expectedImg := test.CommonImageTag - workflow.Spec.PodTemplate.Container.Image = expectedImg - utilruntime.Must(client.Update(context.TODO(), workflow)) - result, objects, err = handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - var deployment *v1.Deployment - for _, o := range objects { - if _, ok := o.(*v1.Deployment); ok { - deployment = o.(*v1.Deployment) - assert.Equal(t, expectedImg, deployment.Spec.Template.Spec.Containers[0].Image) - assert.Equal(t, v1alpha08.DefaultContainerName, deployment.Spec.Template.Spec.Containers[0].Name) - break - } - } - assert.NotNil(t, deployment) -} - -func Test_CheckDeploymentRolloutAfterCMChange(t *testing.T) { - workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name()) - - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow). - WithStatusSubresource(workflow). - Build() - stateSupport := fakeReconcilerSupport(client) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := NewDeploymentReconciler(stateSupport, NewObjectEnsurers(stateSupport)) - - result, objects, err := handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - - userPropsCM := &corev1.ConfigMap{} - err = client.Get(context.TODO(), types.NamespacedName{Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow), Namespace: t.Name()}, userPropsCM) - assert.NoError(t, err) - - // Second reconciliation, we do change the configmap and that must rollout the deployment - var managedPropsCM *corev1.ConfigMap - var checksum string - for _, o := range objects { - if _, ok := o.(*v1.Deployment); ok { - deployment := o.(*v1.Deployment) - assert.NotNil(t, deployment.Spec.Template.ObjectMeta.Annotations) - assert.Contains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.Checksum) - checksum = deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] - assert.NotContains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.RestartedAt) - } - if _, ok := o.(*corev1.ConfigMap); ok { - cm := o.(*corev1.ConfigMap) - if cm.Name == workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow) { - managedPropsCM = cm - } - } - } - assert.NotNil(t, managedPropsCM) - - currentProps := userPropsCM.Data[workflowproj.ApplicationPropertiesFileName] - props, err := properties.LoadString(currentProps) - assert.Nil(t, err) - props.MustSet("test.property", "test.value") - userPropsCM.Data[workflowproj.ApplicationPropertiesFileName] = props.String() - utilruntime.Must(client.Update(context.TODO(), userPropsCM)) - result, objects, err = handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - for _, o := range objects { - if _, ok := o.(*v1.Deployment); ok { - deployment := o.(*v1.Deployment) - assert.Contains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.RestartedAt) - assert.Contains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.Checksum) - newChecksum := deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] - assert.NotEmpty(t, newChecksum) - assert.NotEqual(t, newChecksum, checksum) - break - } - } -} - -func Test_CheckDeploymentUnchangedAfterCMChangeOtherKeys(t *testing.T) { - workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name()) - - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow). - WithStatusSubresource(workflow). - Build() - stateSupport := fakeReconcilerSupport(client) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := NewDeploymentReconciler(stateSupport, NewObjectEnsurers(stateSupport)) - - result, objects, err := handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - - userPropsCM := &corev1.ConfigMap{} - err = client.Get(context.TODO(), types.NamespacedName{Name: workflowproj.GetWorkflowUserPropertiesConfigMapName(workflow), Namespace: t.Name()}, userPropsCM) - assert.NoError(t, err) - - // Second reconciliation, we do change the configmap and that must not rollout the deployment - // because we're not updating the application.properties key - var managedPropsCM *corev1.ConfigMap - var checksum string - for _, o := range objects { - if _, ok := o.(*v1.Deployment); ok { - deployment := o.(*v1.Deployment) - assert.NotNil(t, deployment.Spec.Template.ObjectMeta.Annotations) - assert.Contains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.Checksum) - checksum = deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] - assert.NotContains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.RestartedAt) - } - if _, ok := o.(*corev1.ConfigMap); ok { - cm := o.(*corev1.ConfigMap) - if cm.Name == workflowproj.GetWorkflowManagedPropertiesConfigMapName(workflow) { - managedPropsCM = cm - } - } - } - assert.NotNil(t, managedPropsCM) - - userPropsCM.Data["other.key"] = "useless.key = value" - utilruntime.Must(client.Update(context.TODO(), userPropsCM)) - result, objects, err = handler.Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.NotEmpty(t, objects) - assert.True(t, result.Requeue) - for _, o := range objects { - if _, ok := o.(*v1.Deployment); ok { - deployment := o.(*v1.Deployment) - assert.NotContains(t, deployment.Spec.Template.ObjectMeta.Annotations, metadata.RestartedAt) - newChecksum := deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] - assert.NotEmpty(t, newChecksum) - assert.Equal(t, newChecksum, checksum) - break - } - } -} diff --git a/internal/controller/profiles/preview/disruption_budget_handler.go b/internal/controller/profiles/preview/disruption_budget_handler.go deleted file mode 100644 index 78882628..00000000 --- a/internal/controller/profiles/preview/disruption_budget_handler.go +++ /dev/null @@ -1,105 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 preview - -import ( - "context" - "fmt" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/workflowproj" - - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/log" - - policyv1 "k8s.io/api/policy/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - "github.com/kubesmarts/logic-operator/utils/kubernetes" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" -) - -type podDisruptionBudgetHandler struct { - stateSupport *common.StateSupport - podDisruptionBudget common.ObjectEnsurer -} - -type PodDisruptionBudgetHandler interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) (client.Object, error) -} - -func NewPodDisruptionBudgetHandler(support *common.StateSupport) PodDisruptionBudgetHandler { - return podDisruptionBudgetHandler{ - stateSupport: support, - podDisruptionBudget: common.NewObjectEnsurer(support.C, common.PodDisruptionBudgetCreator), - } -} - -func (h podDisruptionBudgetHandler) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow) (client.Object, error) { - if workflow.Spec.PodTemplate.DeploymentModel == operatorapi.KnativeDeploymentModel { - return nil, nil - } - - createOrUpdate := false - if !kubernetes.IsEmptyPodDisruptionBudgetSpec(workflow.Spec.PodTemplate.PodDisruptionBudget) { - klog.V(log.D).Infof("Finding HPA for workflow: %s/%s", workflow.Namespace, workflow.Name) - hpa, err := kubernetes.FindHPAForWorkflow(ctx, h.stateSupport.C, workflow.Namespace, workflow.Name) - if err != nil { - return nil, fmt.Errorf("failed to find a potential HorizontalPodAutoscaler for workflow: %s/%s: %v", workflow.Namespace, workflow.Name, err) - } - if hpa != nil { - klog.V(log.D).Infof("HPA %s/%s was found for workflow %s/%s", hpa.Namespace, hpa.Name, workflow.Namespace, workflow.Name) - // The HPA determines the replicas. Be sure that the workflow can't be later downscaled to a number of replicas that blocks a drain. - // And, also that the user didn't voluntary scaled the workflow to 0. - createOrUpdate = kubernetes.HPAMinReplicasIsGreaterThan(hpa, int32(1)) && !workflowdef.IsScaledToZero(workflow) - } else { - // The replicas are determined from the workflow spec. Be sure that the number of replicas don't block a drain. - createOrUpdate = workflowdef.ReplicasIsGreaterThan(workflow, int32(1)) - } - } - - if createOrUpdate { - pdb, _, err := h.podDisruptionBudget.Ensure(ctx, workflow, func(object client.Object) controllerutil.MutateFn { - return func() error { - targetPdb := object.(*policyv1.PodDisruptionBudget) - targetPdb.Spec.Selector = &metav1.LabelSelector{ - MatchLabels: workflowproj.GetSelectorLabels(workflow), - } - kubernetes.ApplyPodDisruptionBudgetSpec(targetPdb, workflow.Spec.PodTemplate.PodDisruptionBudget) - return nil - } - }) - if err != nil { - return nil, fmt.Errorf("failed to create or update PodDiscruptionBudget for workflow's deployment %s/%s: %v", workflow.Namespace, workflow.Name, err) - } - return pdb, nil - } else { - // Remove a potential previously created PDB if any. - if err := kubernetes.SafeDeletePodDisruptionBudget(ctx, h.stateSupport.C, workflow.Namespace, workflow.Name); err != nil { - return nil, err - } - return nil, nil - } -} diff --git a/internal/controller/profiles/preview/object_creators_preview.go b/internal/controller/profiles/preview/object_creators_preview.go deleted file mode 100644 index c20ee6db..00000000 --- a/internal/controller/profiles/preview/object_creators_preview.go +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 preview - -import ( - "fmt" - - appsv1 "k8s.io/api/apps/v1" - v1 "k8s.io/api/core/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -const ( - imageOpenShiftTriggers = "image.openshift.io/triggers" - imageOpenShiftTriggersValueFormat = "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"%s\"},\"fieldPath\":\"spec.template.spec.containers[?(@.name==\\\"" + v1alpha08.DefaultContainerName + "\\\")].image\"}]" -) - -// addOpenShiftImageTriggerDeploymentMutateVisitor adds the ImageStream trigger annotation to the Deployment -// -// See: https://docs.openshift.com/container-platform/4.13/openshift_images/triggering-updates-on-imagestream-changes.html -func addOpenShiftImageTriggerDeploymentMutateVisitor(workflow *v1alpha08.SonataFlow, image string) common.MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - if workflow.HasContainerSpecImage() { - // noop since we don't need to build anything - return func() error { - return nil - } - } - return func() error { - annotations := make(map[string]string, len(object.(*appsv1.Deployment).Annotations)+1) - for k, v := range object.(*appsv1.Deployment).Annotations { - annotations[k] = v - } - annotations[imageOpenShiftTriggers] = fmt.Sprintf(imageOpenShiftTriggersValueFormat, image) - object.(*appsv1.Deployment).Annotations = annotations - return nil - } - } -} - -// mountConfigMapsMutateVisitor mounts the required configMaps in the SonataFlow instance -func mountConfigMapsMutateVisitor(workflow *operatorapi.SonataFlow, userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) common.MutateVisitor { - return func(object client.Object) controllerutil.MutateFn { - return func() error { - var podTemplateSpec *v1.PodSpec - - if workflow.IsKnativeDeployment() { - ksvc := object.(*servingv1.Service) - podTemplateSpec = &ksvc.Spec.Template.Spec.PodSpec - } else { - deployment := object.(*appsv1.Deployment) - podTemplateSpec = &deployment.Spec.Template.Spec - if err := kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM, managedPropsCM); err != nil { - return err - } - } - - _, idx := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, podTemplateSpec) - - if len(podTemplateSpec.Volumes) == 0 { - podTemplateSpec.Volumes = make([]v1.Volume, 0, 1) - } - if len(podTemplateSpec.Containers[idx].VolumeMounts) == 0 { - podTemplateSpec.Containers[idx].VolumeMounts = make([]v1.VolumeMount, 0, 1) - } - - defaultResourcesVolume := v1.Volume{Name: constants.ConfigMapWorkflowPropsVolumeName, VolumeSource: v1.VolumeSource{Projected: &v1.ProjectedVolumeSource{}}} - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, userPropsCM.Name, v1.KeyToPath{Key: workflowproj.ApplicationPropertiesFileName, Path: workflowproj.ApplicationPropertiesFileName}) - kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected, managedPropsCM.Name, v1.KeyToPath{Key: workflowproj.GetManagedPropertiesFileName(workflow), Path: workflowproj.GetManagedPropertiesFileName(workflow)}) - kubeutil.AddOrReplaceVolume(podTemplateSpec, defaultResourcesVolume) - kubeutil.AddOrReplaceVolumeMount(&podTemplateSpec.Containers[idx], - kubeutil.VolumeMount(constants.ConfigMapWorkflowPropsVolumeName, true, quarkusProdConfigMountPath)) - - return nil - } - } -} diff --git a/internal/controller/profiles/preview/profile_preview.go b/internal/controller/profiles/preview/profile_preview.go deleted file mode 100644 index 0181e383..00000000 --- a/internal/controller/profiles/preview/profile_preview.go +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 preview - -import ( - "time" - - "k8s.io/client-go/rest" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "k8s.io/client-go/tools/record" - - "github.com/kubesmarts/logic-operator/internal/controller/discovery" - - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" -) - -var _ profiles.ProfileReconciler = &previewProfile{} - -type previewProfile struct { - common.Reconciler -} - -const ( - requeueAfterStartingBuild = 3 * time.Minute - requeueWhileWaitForBuild = 1 * time.Minute - requeueWhileWaitForPlatform = 5 * time.Second - - quarkusProdConfigMountPath = "/deployments/config" -) - -// ObjectEnsurers is a struct for the objects that ReconciliationState needs to create in the platform for the preview profile. -// ReconciliationState that needs access to it must include this struct as an attribute and initialize it in the profile builder. -// Use NewObjectEnsurers to facilitate building this struct -type ObjectEnsurers struct { - // deployment for this ensurer. Don't call it directly, use DeploymentByDeploymentModel instead - deployment common.ObjectEnsurerWithPlatform - // kservice Knative Serving deployment for this ensurer. Don't call it directly, use DeploymentByDeploymentModel instead - kservice common.ObjectEnsurerWithPlatform - // service for this ensurer. Don't call it directly, use ServiceByDeploymentModel instead - service common.ObjectEnsurer - // serviceMonitor for this ensurer. Don't call it directly, use ServiceMonitorByDeploymentModel instead - serviceMonitor common.ObjectEnsurer - userPropsConfigMap common.ObjectEnsurer - managedPropsConfigMap common.ObjectEnsurerWithPlatform -} - -// DeploymentByDeploymentModel gets the deployment ensurer based on the SonataFlow deployment model -func (o *ObjectEnsurers) DeploymentByDeploymentModel(workflow *v1alpha08.SonataFlow) common.ObjectEnsurerWithPlatform { - if workflow.IsKnativeDeployment() { - return o.kservice - } - return o.deployment -} - -// ServiceByDeploymentModel gets the service ensurer based on the SonataFlow deployment model -func (o *ObjectEnsurers) ServiceByDeploymentModel(workflow *v1alpha08.SonataFlow) common.ObjectEnsurer { - if workflow.IsKnativeDeployment() { - // Knative Serving handles the service - return common.NewNoopObjectEnsurer() - } - return o.service -} - -// ServiceMonitorByDeploymentModel gets the service monitor ensurer based on the SonataFlow deployment model -func (o *ObjectEnsurers) ServiceMonitorByDeploymentModel(workflow *v1alpha08.SonataFlow) common.ObjectEnsurer { - if workflow.IsKnativeDeployment() { - // Do not create service monitor for workflows deployed as Knative service - return common.NewNoopObjectEnsurer() - } - return o.serviceMonitor -} - -// NewObjectEnsurers common.ObjectEnsurer(s) for the preview profile. -func NewObjectEnsurers(support *common.StateSupport) *ObjectEnsurers { - return &ObjectEnsurers{ - deployment: common.NewObjectEnsurerWithPlatform(support.C, common.DeploymentCreator), - kservice: common.NewObjectEnsurerWithPlatform(support.C, common.KServiceCreator), - service: common.NewObjectEnsurer(support.C, common.ServiceCreator), - serviceMonitor: common.NewObjectEnsurer(support.C, common.ServiceMonitorCreator), - userPropsConfigMap: common.NewObjectEnsurer(support.C, common.UserPropsConfigMapCreator), - managedPropsConfigMap: common.NewObjectEnsurerWithPlatform(support.C, common.ManagedPropsConfigMapCreator), - } -} - -// NewProfileReconciler the default profile builder which includes a build state to run an internal build process -// to have an immutable workflow image deployed -func NewProfileReconciler(client client.Client, cfg *rest.Config, recorder record.EventRecorder) profiles.ProfileReconciler { - support := &common.StateSupport{ - C: client, - Cfg: cfg, - Catalog: discovery.NewServiceCatalogForConfig(client, cfg), - Recorder: recorder, - } - // the reconciliation state machine - stateMachine := common.NewReconciliationStateMachine( - &newBuilderState{StateSupport: support, ensurers: NewObjectEnsurers(support)}, - &followBuildStatusState{StateSupport: support}, - &deployWithBuildWorkflowState{StateSupport: support, ensurers: NewObjectEnsurers(support)}, - ) - reconciler := &previewProfile{ - Reconciler: common.NewReconciler(support, stateMachine), - } - - return reconciler -} - -func (p previewProfile) GetProfile() metadata.ProfileType { - return metadata.PreviewProfile -} diff --git a/internal/controller/profiles/preview/profile_preview_test.go b/internal/controller/profiles/preview/profile_preview_test.go deleted file mode 100644 index 1bf98909..00000000 --- a/internal/controller/profiles/preview/profile_preview_test.go +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 preview - -import ( - "context" - "testing" - "time" - - "github.com/kubesmarts/logic-operator/api/version" - - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/rest" - clientruntime "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/utils" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -func Test_Reconciler_ProdCustomPod(t *testing.T) { - workflow := test.GetBaseSonataFlowWithProdProfile(t.Name()) - workflow.Spec.PodTemplate.PodSpec.InitContainers = append(workflow.Spec.PodTemplate.PodSpec.InitContainers, corev1.Container{ - Name: "check-postgres", - Image: "registry.access.redhat.com/ubi9/ubi-micro:latest", - Command: []string{"sh", "-c", "until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo \"Waiting for postgres server\"; sleep 3; done;"}, - }) - workflow.Status.Manager().MarkTrue(api.BuiltConditionType) - workflow.Status.Manager().MarkTrue(api.RunningConditionType) - build := test.GetLocalSucceedSonataFlowBuild(workflow.Name, workflow.Namespace) - platform := test.GetBasePlatformInReadyPhase(workflow.Namespace) - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow, build, platform). - WithStatusSubresource(workflow, build, platform).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - _, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - - // Let's check for the right creation of the workflow (one CM volume, one container with a custom image) - deployment := &appsv1.Deployment{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), deployment) - assert.NoError(t, err) - - assert.Len(t, deployment.Spec.Template.Spec.Volumes, 1) - assert.Len(t, deployment.Spec.Template.Spec.Containers, 1) - assert.Len(t, deployment.Spec.Template.Spec.InitContainers, 1) - assert.Len(t, deployment.Spec.Template.Spec.Containers[0].VolumeMounts, 1) - assert.NotNil(t, deployment.ObjectMeta) - assert.NotNil(t, deployment.ObjectMeta.Labels) - assert.Equal(t, deployment.ObjectMeta.Labels, map[string]string{ - "app": "greeting", - "app.kubernetes.io/instance": "greeting", - "test": "test", - "sonataflow.org/workflow-app": "greeting", - "sonataflow.org/workflow-namespace": workflow.Namespace, - "app.kubernetes.io/name": "greeting", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "app.kubernetes.io/version": version.GetImageTagVersion(), - }) -} - -func Test_reconcilerProdBuildConditions(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - platform := test.GetBasePlatformInReadyPhase(t.Name()) - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow, platform). - WithStatusSubresource(workflow, platform, &operatorapi.SonataFlowBuild{}).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - result, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - - assert.NotNil(t, result.RequeueAfter) - assert.True(t, workflow.Status.IsBuildRunningOrUnknown()) - assert.False(t, workflow.Status.IsReady()) - - // still building - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.Equal(t, requeueWhileWaitForBuild, result.RequeueAfter) - assert.True(t, workflow.Status.IsBuildRunningOrUnknown()) - assert.False(t, workflow.Status.IsReady()) - - // let's finish this build - build := &operatorapi.SonataFlowBuild{} - assert.NoError(t, client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), build)) - build.Status.BuildPhase = operatorapi.BuildPhaseSucceeded - assert.NoError(t, client.Status().Update(context.TODO(), build)) - - // last reconciliation cycle waiting for build - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.Equal(t, requeueWhileWaitForBuild, result.RequeueAfter) - assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) - assert.False(t, workflow.Status.IsReady()) - assert.Equal(t, api.WaitingForDeploymentReason, workflow.Status.GetTopLevelCondition().Reason) - - // now we create the objects - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) - assert.False(t, workflow.Status.IsReady()) - assert.Equal(t, api.WaitingForDeploymentReason, workflow.Status.GetTopLevelCondition().Reason) - - // now with the objects created, it should be running - // let's update the deployment status to available == true - deployment := &appsv1.Deployment{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), deployment) - assert.NoError(t, err) - deployment.Status.Conditions = append(deployment.Status.Conditions, appsv1.DeploymentCondition{ - Type: appsv1.DeploymentAvailable, - Status: corev1.ConditionTrue, - }) - err = client.Status().Update(context.TODO(), deployment) - assert.NoError(t, err) - - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) - assert.NoError(t, err) - assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) - assert.True(t, workflow.Status.IsReady()) -} - -func Test_deployWorkflowReconciliationHandler_handleObjects(t *testing.T) { - workflow := test.GetBaseSonataFlow(t.Name()) - platform := test.GetBasePlatformInReadyPhase(t.Name()) - platform.Spec.Monitoring = &operatorapi.PlatformMonitoringOptionsSpec{Enabled: true} - build := test.GetLocalSucceedSonataFlowBuild(workflow.Name, workflow.Namespace) - client := test.NewKogitoClientBuilderWithOpenShift(). - WithRuntimeObjects(workflow, platform, build). - WithStatusSubresource(workflow, platform, build). - Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := &deployWithBuildWorkflowState{ - StateSupport: fakeReconcilerSupport(client), - ensurers: NewObjectEnsurers(&common.StateSupport{C: client}), - } - result, objects, err := handler.Do(context.TODO(), workflow) - assert.Greater(t, result.RequeueAfter, int64(0)) - assert.NoError(t, err) - assert.NotNil(t, result) - assert.Len(t, objects, 4) - - deployment := &appsv1.Deployment{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), deployment) - assert.NoError(t, err) - assert.NotEmpty(t, deployment.Spec.Template.Spec.Containers[0].Image) - - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), workflow) - assert.NoError(t, err) - assert.False(t, workflow.Status.IsReady()) - assert.Equal(t, api.WaitingForDeploymentReason, workflow.Status.GetTopLevelCondition().Reason) - - serviceMonitor := &prometheus.ServiceMonitor{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), serviceMonitor) - assert.NoError(t, err) - assert.NotEmpty(t, serviceMonitor.Spec) - assert.NotEmpty(t, serviceMonitor.Spec.Selector) - assert.Equal(t, len(serviceMonitor.Spec.Selector.MatchLabels), 2) - assert.Equal(t, serviceMonitor.Spec.Selector.MatchLabels[workflowproj.LabelWorkflow], workflow.Name) - assert.Equal(t, serviceMonitor.Spec.Selector.MatchLabels[workflowproj.LabelWorkflowNamespace], workflow.Namespace) - assert.Equal(t, len(serviceMonitor.Spec.Endpoints), 1) - assert.Equal(t, serviceMonitor.Spec.Endpoints[0].Port, "web") - assert.Equal(t, serviceMonitor.Spec.Endpoints[0].Path, "/q/metrics") -} - -func Test_WorkflowChangedCheck(t *testing.T) { - // we load a workflow with metadata.generation to 0 - workflow := test.GetBaseSonataFlow(t.Name()) - platform := test.GetBasePlatformInReadyPhase(t.Name()) - client := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(workflow, platform). - WithStatusSubresource(workflow, platform, &operatorapi.SonataFlowBuild{}).Build() - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - handler := &deployWithBuildWorkflowState{ - StateSupport: fakeReconcilerSupport(client), - ensurers: NewObjectEnsurers(&common.StateSupport{C: client}), - } - result, objects, err := handler.Do(context.TODO(), workflow) - assert.Greater(t, result.RequeueAfter, int64(time.Second)) - assert.NoError(t, err) - assert.NotNil(t, result) - assert.Len(t, objects, 3) - - // then we load the current workflow - workflowChanged := &operatorapi.SonataFlow{} - err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), workflowChanged) - assert.NoError(t, err) - //we change something within the flow - workflowChanged.Spec.Flow.AutoRetries = true - - // reconcile -> the one in the k8s DB is different, so there's a change. - handler = &deployWithBuildWorkflowState{ - StateSupport: fakeReconcilerSupport(client), - ensurers: NewObjectEnsurers(&common.StateSupport{C: client}), - } - result, objects, err = handler.Do(context.TODO(), workflowChanged) - assert.NoError(t, err) - // no requeue, no objects since the workflow has changed - assert.Equal(t, time.Duration(0), result.RequeueAfter) - assert.False(t, result.Requeue) - assert.Len(t, objects, 0) -} - -func fakeReconcilerSupport(client clientruntime.Client) *common.StateSupport { - return &common.StateSupport{ - C: client, - Recorder: test.NewFakeRecorder(), - Cfg: &rest.Config{}, - } -} diff --git a/internal/controller/profiles/preview/states_preview.go b/internal/controller/profiles/preview/states_preview.go deleted file mode 100644 index bd998f7c..00000000 --- a/internal/controller/profiles/preview/states_preview.go +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 preview - -import ( - "context" - "fmt" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/utils" - - klog "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/builder" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" -) - -type newBuilderState struct { - *common.StateSupport - ensurers *ObjectEnsurers -} - -func (h *newBuilderState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.GetTopLevelCondition().IsUnknown() || - workflow.Status.IsWaitingForPlatform() || - workflow.Status.IsBuildFailed() -} - -func (h *newBuilderState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - pl, err := platform.GetActivePlatform(ctx, h.C, workflow.Namespace, true) - if err != nil { - if errors.IsNotFound(err) { - workflow.Status.Manager().MarkFalsef(api.BuiltConditionType, api.WaitingForPlatformReason, - "No active Platform for namespace %s so the workflow cannot be built.", workflow.Namespace) - _, err = h.PerformStatusUpdate(ctx, workflow) - return ctrl.Result{RequeueAfter: requeueWhileWaitForPlatform}, nil, err - } - // We won't record events here to avoid spamming multiple events to the object, the status should alert the admin - // since a namespace without a platform means incorrect configuration. - klog.V(log.E).ErrorS(err, "Failed to get active platform") - return ctrl.Result{RequeueAfter: requeueWhileWaitForPlatform}, nil, err - } - - // Perform status updated to ensure workflow.Status.Services references are set before properties calculation. - _, err = h.PerformStatusUpdate(ctx, workflow) - // Ensure the user and managed properties are prepared before starting the build process, and thus, we make them - // available at build time. - userPropsCM, _, err := h.ensurers.userPropsConfigMap.Ensure(ctx, workflow) - if err != nil { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.ExternalResourcesNotFoundReason, fmt.Sprintf("Unable to retrieve the user properties config map: %v", err)) - _, err = h.PerformStatusUpdate(ctx, workflow) - return ctrl.Result{}, nil, err - } - - _, _, err = h.ensurers.managedPropsConfigMap.Ensure(ctx, workflow, pl, - common.ManagedPropertiesMutateVisitor(ctx, h.StateSupport.Catalog, workflow, pl, userPropsCM.(*corev1.ConfigMap))) - if err != nil { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.ExternalResourcesNotFoundReason, fmt.Sprintf("Unable to retrieve the managed properties config map: %v", err)) - _, err = h.PerformStatusUpdate(ctx, workflow) - return ctrl.Result{}, nil, err - } - - // If there is an active platform we have got all the information to build but... - // ...let's check before if we have got already a build! - buildManager := builder.NewSonataFlowBuildManager(ctx, h.C) - build, err := buildManager.GetOrCreateBuild(workflow) - if err != nil { - //If we are not able to retrieve or create a Build CR for this Workflow we will mark - klog.V(log.E).ErrorS(err, "Failed to retrieve or create a Build CR") - workflow.Status.Manager().MarkFalsef(api.BuiltConditionType, api.BuildFailedReason, - "Failed to retrieve or create a Build CR in namespace: %s", workflow.Namespace) - _, err = h.PerformStatusUpdate(ctx, workflow) - return ctrl.Result{}, nil, err - } - - if build.Status.BuildPhase != operatorapi.BuildPhaseFailed { - workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildIsRunningReason, "") - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForBuildReason, "") - _, err = h.PerformStatusUpdate(ctx, workflow) - h.Recorder.Eventf(workflow, corev1.EventTypeNormal, api.BuildIsRunningReason, "Workflow %s build has started.", workflow.Name) - } else { - klog.V(log.I).InfoS("Build is in failed state, you can mark the build to rebuild by setting to 'true' the ", "annotation", operatorapi.BuildRestartAnnotation) - } - - return ctrl.Result{RequeueAfter: requeueAfterStartingBuild}, nil, err -} - -func (h *newBuilderState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - //By default, we don't want to perform anything after the reconciliation, and so we will simply return no error - return nil -} - -type followBuildStatusState struct { - *common.StateSupport -} - -func (h *followBuildStatusState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - return workflow.Status.IsBuildRunningOrUnknown() || workflow.Status.IsWaitingForBuild() -} - -func (h *followBuildStatusState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - // Let's retrieve the build to check the status - build, err := builder.NewSonataFlowBuildManager(ctx, h.C).GetOrCreateBuild(workflow) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to get or create the build for the workflow.") - workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildFailedReason, err.Error()) - if _, err = h.PerformStatusUpdate(ctx, workflow); err != nil { - return ctrl.Result{}, nil, err - } - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err - } - - if build.Status.BuildPhase == operatorapi.BuildPhaseSucceeded { - klog.V(log.I).InfoS("Workflow build has finished") - if workflow.Status.IsReady() { - // Rollout our deployment to take the latest changes in the new image. - if err := common.DeploymentManager(h.C).RolloutDeployment(ctx, workflow); err != nil { - return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err - } - h.Recorder.Eventf(workflow, corev1.EventTypeNormal, api.WaitingForDeploymentReason, "Rolling out workflow %s deployment.", workflow.Name) - } - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForDeploymentReason, "Build has finished, rolling out deployment") - //If we have finished a build and the workflow is not running, we will start the provisioning phase - workflow.Status.Manager().MarkTrue(api.BuiltConditionType) - _, err = h.PerformStatusUpdate(ctx, workflow) - h.Recorder.Eventf(workflow, corev1.EventTypeNormal, api.BuildSuccessfulReason, "Workflow %s build has been finished successfully.", workflow.Name) - } else if build.Status.BuildPhase == operatorapi.BuildPhaseFailed || build.Status.BuildPhase == operatorapi.BuildPhaseError { - workflow.Status.Manager().MarkFalsef(api.BuiltConditionType, api.BuildFailedReason, - "Workflow %s build failed. Error: %s", workflow.Name, build.Status.Error) - _, err = h.PerformStatusUpdate(ctx, workflow) - h.Recorder.Eventf(workflow, corev1.EventTypeWarning, api.BuildFailedReason, "Workflow %s build has failed. Error: %s", workflow.Name, build.Status.Error) - } else if build.Status.BuildPhase == operatorapi.BuildPhaseRunning && !workflow.Status.IsBuildRunning() { - workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildIsRunningReason, "") - _, err = h.PerformStatusUpdate(ctx, workflow) - h.Recorder.Eventf(workflow, corev1.EventTypeNormal, api.BuildIsRunningReason, "Workflow %s build is running.", workflow.Name) - } - - if err != nil { - return ctrl.Result{}, nil, err - } - - return ctrl.Result{RequeueAfter: requeueWhileWaitForBuild}, nil, nil -} - -func (h *followBuildStatusState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - //By default, we don't want to perform anything after the reconciliation, and so we will simply return no error - return nil -} - -type deployWithBuildWorkflowState struct { - *common.StateSupport - ensurers *ObjectEnsurers - deploymentVisitors []common.MutateVisitor -} - -func (h *deployWithBuildWorkflowState) CanReconcile(workflow *operatorapi.SonataFlow) bool { - // If we have a built ready, we should deploy the object - return workflow.Status.GetCondition(api.BuiltConditionType).IsTrue() -} - -func (h *deployWithBuildWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { - // Guard to avoid errors while getting a new builder manager. - // Maybe we can do typed errors in the buildManager and - // have something like sonataerr.IsPlatformNotFound(err) instead. - _, err := platform.GetActivePlatform(ctx, h.C, workflow.Namespace, true) - if err != nil { - workflow.Status.Manager().MarkFalsef(api.RunningConditionType, api.WaitingForPlatformReason, - "No active Platform for namespace %s so the resWorkflowDef cannot be deployed. Waiting for an active platform", workflow.Namespace) - return ctrl.Result{RequeueAfter: requeueWhileWaitForPlatform}, nil, err - } - - buildManager := builder.NewSonataFlowBuildManager(ctx, h.C) - build, err := buildManager.GetOrCreateBuild(workflow) - if err != nil { - return ctrl.Result{}, nil, err - } - - hasChanged, err := h.isWorkflowChanged(workflow) - if err != nil { - return ctrl.Result{}, nil, err - } - if hasChanged { // Let's check that the 2 resWorkflowDef definition are different - if err = buildManager.MarkToRestart(build); err != nil { - return ctrl.Result{}, nil, err - } - workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildIsRunningReason, "Build marked to restart") - workflow.Status.Manager().MarkUnknown(api.RunningConditionType, "", "") - _, err = h.PerformStatusUpdate(ctx, workflow) - h.Recorder.Eventf(workflow, corev1.EventTypeNormal, api.BuildMarkedToRestartReason, "Workflow %s will start a new build.", workflow.Name) - return ctrl.Result{Requeue: false}, nil, err - } - - // didn't change, business as usual - result, objs, err := NewDeploymentReconciler(h.StateSupport, h.ensurers).reconcileWithImage(ctx, workflow, build.Status.ImageTag) - if err != nil { - workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentFailureReason, fmt.Sprintf("Error in deploy the workflow:%s", err)) - _, err = h.PerformStatusUpdate(ctx, workflow) - return result, nil, err - } - return result, objs, err -} - -func (h *deployWithBuildWorkflowState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { - // Clean up the outdated Knative revisions, if any - return common.CleanupOutdatedRevisions(ctx, h.Cfg, workflow) -} - -// isWorkflowChanged checks whether the contents of .spec.flow of the given workflow has changed. -func (h *deployWithBuildWorkflowState) isWorkflowChanged(workflow *operatorapi.SonataFlow) (bool, error) { - // Added this guard for backward compatibility for workflows deployed with a previous operator version, so we won't kick thousands of builds on users' cluster. - // After this reconciliation cycle, the CRC should be updated - if workflow.Status.FlowCRC == 0 { - return false, nil - } - actualCRC, err := utils.Crc32Checksum(workflow.Spec.Flow) - if err != nil { - return false, err - } - return actualCRC != workflow.Status.FlowCRC, nil -} diff --git a/internal/controller/profiles/preview/states_preview_test.go b/internal/controller/profiles/preview/states_preview_test.go deleted file mode 100644 index 2ab6d9de..00000000 --- a/internal/controller/profiles/preview/states_preview_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 preview - -import ( - "testing" - - "github.com/kubesmarts/logic-operator/utils" - - "github.com/serverlessworkflow/sdk-go/v2/model" - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/test" -) - -func Test_deployWithBuildWorkflowState_isWorkflowChanged(t *testing.T) { - workflow1 := test.GetBaseSonataFlow(t.Name()) - workflow2 := test.GetBaseSonataFlow(t.Name()) - workflow1.Status.FlowCRC, _ = utils.Crc32Checksum(workflow1.Spec.Flow) - workflow2.Status.FlowCRC, _ = utils.Crc32Checksum(workflow2.Spec.Flow) - deployWithBuildWorkflowState := &deployWithBuildWorkflowState{ - StateSupport: &common.StateSupport{C: test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow1).Build()}, - } - - hasChanged, err := deployWithBuildWorkflowState.isWorkflowChanged(workflow2) - assert.NoError(t, err) - assert.False(t, hasChanged) - - // change workflow2 - workflow2.Spec.Flow.Metadata = model.Metadata{ - "string": model.Object{ - StringValue: "test", - }, - } - - hasChanged, err = deployWithBuildWorkflowState.isWorkflowChanged(workflow2) - assert.NoError(t, err) - assert.True(t, hasChanged) -} diff --git a/internal/controller/profiles/profile.go b/internal/controller/profiles/profile.go deleted file mode 100644 index b3de141b..00000000 --- a/internal/controller/profiles/profile.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 profiles - -import ( - "context" - - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/workflowproj" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -// ProfileReconciler is the public interface to have access to this package and perform the actual reconciliation flow. -// -// There are a few concepts in this package that you need to understand before attempting to maintain it: -// -// 1. ProfileReconciler: it's the main interface that internal structs implement via the baseReconciler. -// Every profile must embed the baseReconciler. -// -// 2. stateSupport: is a struct with a few support objects passed around the reconciliation states like the client and logger. -// -// 3. reconciliationStateMachine: is a struct within the ProfileReconciler that do the actual reconciliation. -// Each part of the reconciliation algorithm is a ReconciliationState that will be executed based on the ReconciliationState.CanReconcile call. -// -// 4. ReconciliationState: is where your business code should be focused on. Each state should react to a specific operatorapi.SonataFlowConditionType. -// The least conditions your state handles, the better. -// The ReconciliationState can provide specific code that will only be triggered if the workflow is in that specific condition. -// -// 5. objectCreator: are functions to create a specific Kubernetes object based on a given workflow instance. This function should return the desired default state. -// -// 6. mutateVisitor: is a function that states can pass to defaultObjectEnsurer that will be applied to a given live object during the reconciliation cycle. -// For example, if you wish to guarantee that an image in a specific container in the Deployment that you control and own won't change, make sure that your -// mutate function guarantees that. -// -// 7. defaultObjectEnsurer: is a struct for a given objectCreator to control the reconciliation and merge conditions to an object. -// A ReconciliationState may or may not have one or more ensurers. Depends on their role. There are states that just read objects, so no need to keep their desired state. -// -// See the already implemented reconciliation profiles to have a better understanding. -// -// While debugging, focus on the ReconciliationState(s), not in the profile implementation since the base algorithm is the same for every profile. -type ProfileReconciler interface { - Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) - GetProfile() metadata.ProfileType -} - -// ReconciliationState is an interface implemented internally by different reconciliation algorithms to perform the adequate logic for a given workflow profile -type ReconciliationState interface { - // CanReconcile checks if this state can perform its reconciliation task - CanReconcile(workflow *operatorapi.SonataFlow) bool - // Do perform the reconciliation task. It returns the controller result, the objects updated, and an error if any. - // Objects can be nil if the reconciliation state doesn't perform any updates in any Kubernetes object. - Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) - // PostReconcile performs the actions to perform after the reconciliation that are not mandatory - PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error -} - -// IsDevProfile is an alias for workflowproj.IsDevProfile -var IsDevProfile = workflowproj.IsDevProfile - -// IsGitOpsProfile is an alias for workflowproj.IsGitOpsProfile -var IsGitOpsProfile = workflowproj.IsGitOpsProfile diff --git a/internal/controller/profiles/profile_test.go b/internal/controller/profiles/profile_test.go deleted file mode 100644 index 1e7cda6f..00000000 --- a/internal/controller/profiles/profile_test.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 profiles - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/test" -) - -func Test_workflowIsDevProfile(t *testing.T) { - workflowWithDevProfile := test.GetBaseSonataFlowWithDevProfile(t.Name()) - assert.True(t, IsDevProfile(workflowWithDevProfile)) - - workflowWithNoProfile := test.GetBaseSonataFlow(t.Name()) - assert.False(t, IsDevProfile(workflowWithNoProfile)) - - workflowWithProdProfile := test.GetBaseSonataFlowWithProdProfile(t.Name()) - assert.False(t, IsDevProfile(workflowWithProdProfile)) -} - -func Test_workflowGitOpsProfile(t *testing.T) { - workflowWithDevProfile := test.GetBaseSonataFlowWithDevProfile(t.Name()) - assert.False(t, IsGitOpsProfile(workflowWithDevProfile)) - - workflowWithNoProfile := test.GetBaseSonataFlow(t.Name()) - assert.False(t, IsGitOpsProfile(workflowWithNoProfile)) - - workflowWithProdProfile := test.GetBaseSonataFlowWithProdProfile(t.Name()) - assert.False(t, IsGitOpsProfile(workflowWithProdProfile)) - - workflowWithGitopsProfile := test.GetBaseSonataFlowWithGitopsProfile(t.Name()) - assert.True(t, IsGitOpsProfile(workflowWithGitopsProfile)) -} diff --git a/internal/controller/sonataflow_controller.go b/internal/controller/sonataflow_controller.go deleted file mode 100644 index 5d55220f..00000000 --- a/internal/controller/sonataflow_controller.go +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - "time" - - "github.com/kubesmarts/logic-operator/utils/kubernetes" - - autoscalingv2 "k8s.io/api/autoscaling/v2" - pkgbuilder "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/predicate" - - v1 "k8s.io/api/policy/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles" - "github.com/kubesmarts/logic-operator/internal/manager" - - "github.com/kubesmarts/logic-operator/internal/controller/eventing" - - "github.com/kubesmarts/logic-operator/utils" - - "k8s.io/client-go/util/retry" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/properties" - "github.com/kubesmarts/logic-operator/internal/controller/workflowdef" - - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/monitoring" - - "github.com/kubesmarts/logic-operator/api/metadata" - profilescommon "github.com/kubesmarts/logic-operator/internal/controller/profiles/common" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - profilesfactory "github.com/kubesmarts/logic-operator/internal/controller/profiles/factory" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/rest" - - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/api" - "github.com/kubesmarts/logic-operator/log" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - - ctrlevent "sigs.k8s.io/controller-runtime/pkg/event" -) - -// SonataFlowReconciler reconciles a SonataFlow object -type SonataFlowReconciler struct { - Client client.Client - Scheme *runtime.Scheme - Config *rest.Config - Recorder record.EventRecorder -} - -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflows,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflows/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflows/scale,verbs=get;update;patch -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflows/finalizers,verbs=update -//+kubebuilder:rbac:groups="monitoring.coreos.com",resources=servicemonitors,verbs=get;list;watch;create;update;delete -//+kubebuilder:rbac:groups="serving.knative.dev",resources=revisions,verbs=list;watch;delete -//+kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;create;update;patch;delete - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// the SonataFlow object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.2/pkg/reconcile -func (r *SonataFlowReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - - // Make sure the operator is allowed to act on namespace - if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.Client, req.Namespace); err != nil { - return reconcile.Result{}, err - } else if !ok { - klog.V(log.I).InfoS("Ignoring request because the operator hasn't got the permissions to work on namespace", "namespace", req.Namespace) - return reconcile.Result{}, nil - } - - // Fetch the Workflow instance - workflow := &operatorapi.SonataFlow{} - err := r.Client.Get(ctx, req.NamespacedName, workflow) - if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - klog.V(log.E).ErrorS(err, "Failed to get SonataFlow") - return ctrl.Result{}, err - } - - r.setDefaults(workflow) - // If the workflow is being deleted, execute the associated finalizers - if workflow.DeletionTimestamp != nil { - return r.applyFinalizers(ctx, workflow) - } - - // Initial recon cycles initializes the WorkflowFinalizer, the replicas, and early populate the scale selector. - if !profiles.IsDevProfile(workflow) { - update := false - if !controllerutil.ContainsFinalizer(workflow, constants.WorkflowFinalizer) { - klog.V(log.D).Infof("Adding finalizer to workflow %s/%s for generation: %d, resourceVersion: %s.", workflow.Name, workflow.Namespace, workflow.Generation, workflow.ResourceVersion) - controllerutil.AddFinalizer(workflow, constants.WorkflowFinalizer) - update = true - } - if !workflowdef.HasReplicas(workflow) { - klog.V(log.D).Infof("Adding replicas to workflow %s/%s for generation: %d, resourceVersion: %s.", workflow.Name, workflow.Namespace, workflow.Generation, workflow.ResourceVersion) - workflow.Spec.PodTemplate.Replicas = profilescommon.GetReplicasOrDefault(workflow) - update = true - } - if update { - if err := r.Client.Update(ctx, workflow); err != nil { - klog.V(log.E).ErrorS(err, "Failed to update workflow.", "workflow", "namespace", workflow.Name, workflow.Namespace) - return ctrl.Result{}, err - } - return reconcile.Result{}, nil - } - - if !workflowdef.HasScaleSelector(workflow) { - klog.V(log.D).Infof("Adding scale selector to workflow %s/%s for generation: %d, resourceVersion: %s.", workflow.Name, workflow.Namespace, workflow.Generation, workflow.ResourceVersion) - workflow.Status.SetSelector(workflowdef.GenerateScaleSelector(workflow)) - if err := r.Client.Status().Update(ctx, workflow); err != nil { - klog.V(log.E).ErrorS(err, "Failed to update workflow status when adding the scale selector.", "workflow", "namespace", workflow.Name, workflow.Namespace) - return ctrl.Result{}, err - } - return reconcile.Result{}, nil - } - } - - // Only process resources assigned to the operator - if !platform.IsOperatorHandlerConsideringLock(ctx, r.Client, req.Namespace, workflow) { - klog.V(log.I).InfoS("Ignoring request because resource is not assigned to current operator") - return reconcile.Result{}, nil - } - return profilesfactory.NewReconciler(r.Client, r.Config, r.Recorder, workflow).Reconcile(ctx, workflow) -} - -// TODO: move to webhook see https://github.com/kubesmarts/logic-operator/pull/239 -func (r *SonataFlowReconciler) setDefaults(workflow *operatorapi.SonataFlow) { - if workflow.Annotations == nil { - workflow.Annotations = map[string]string{} - } - profile := metadata.GetProfileOrDefault(workflow.Annotations) - workflow.Annotations[metadata.Profile] = string(profile) - if profile == metadata.DevProfile { - workflow.Spec.PodTemplate.DeploymentModel = operatorapi.KubernetesDeploymentModel - } -} - -// applyFinalizers Manages the execution of the workflow finalizers. -func (r *SonataFlowReconciler) applyFinalizers(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) { - if controllerutil.ContainsFinalizer(workflow, constants.TriggerFinalizer) { - if err := r.cleanupTriggers(ctx, workflow); err != nil { - return ctrl.Result{}, err - } - } - if controllerutil.ContainsFinalizer(workflow, constants.WorkflowFinalizer) { - var wasScheduled = false - var err error - if !workflow.Status.FinalizerSucceed && workflow.Status.FinalizerAttempts < constants.MaxWorkflowFinalizerAttempts { - now := metav1.Now() - if isTooFastToReprogramFinalizerAttempt(workflow.Status.LastTimeFinalizerAttempt, now) { - // at this point the Recon cycle might derive from the latest status update, or other source, give some more time before scheduling a new deletion notification. - klog.V(log.D).Infof("Too fast to to schedule a new workflow deletion notification for workflow %s/%s generation: %d, resourceVersion: %s, programming a new Request.", workflow.Namespace, workflow.Name, workflow.Generation, workflow.ResourceVersion) - return ctrl.Result{RequeueAfter: 2 * time.Second}, nil - } - workflow.Status.FinalizerAttempts = workflow.Status.FinalizerAttempts + 1 - workflow.Status.LastTimeFinalizerAttempt = &now - if err = r.Client.Status().Update(ctx, workflow); err != nil { - return ctrl.Result{}, err - } - if wasScheduled, err = scheduleWorkflowDeletionNotification(r.Client, workflow); err != nil { - remaining := constants.MaxWorkflowFinalizerAttempts - workflow.Status.FinalizerAttempts - if remaining > 0 { - klog.V(log.E).ErrorS(err, fmt.Sprintf("Failed to schedule workflow deletion notification, %d remaining attempts are left", remaining)) - } else { - klog.V(log.E).ErrorS(err, "Failed to schedule workflow deletion notification, no attempts are left.", "workflow", "namespace", workflow.Name, workflow.Namespace) - } - return ctrl.Result{RequeueAfter: constants.WorkflowFinalizerSchedulingRetryInterval}, nil - } - } - if wasScheduled { - return ctrl.Result{RequeueAfter: constants.WorkflowFinalizerRetryInterval}, nil - } else { - controllerutil.RemoveFinalizer(workflow, constants.WorkflowFinalizer) - if err := r.Client.Update(ctx, workflow); err != nil { - return ctrl.Result{}, err - } - } - } - return ctrl.Result{}, nil -} - -func isTooFastToReprogramFinalizerAttempt(lastTimeFinalizerAttempt *metav1.Time, now metav1.Time) bool { - if lastTimeFinalizerAttempt != nil { - delta := now.Sub(lastTimeFinalizerAttempt.Time) - return delta < constants.WorkflowFinalizerRetryInterval-1*time.Second - } - return false -} - -func scheduleWorkflowDeletionNotification(cli client.Client, workflow *operatorapi.SonataFlow) (bool, error) { - if eventTargetUrl, err := eventing.GetWorkflowDefinitionEventsTargetURL(cli, workflow); err != nil { - return false, fmt.Errorf("failed to get workflow definition events target url to send the workflow definition status update event: %v", err) - } else { - if len(eventTargetUrl) > 0 { - manager.GetSFCWorker().RunAsync(func() { - wf := *workflow.DeepCopy() - if err := notifyWorkflowDeletion(cli, &wf, eventTargetUrl); err != nil { - klog.V(log.E).ErrorS(err, "Failed to notify workflow deletion, controller will schedule a new retry if remaining attempts > 0.", "workflow", "namespace", workflow.Name, workflow.Namespace) - } - }) - return true, nil - } - } - return false, nil -} - -func notifyWorkflowDeletion(cli client.Client, workflow *operatorapi.SonataFlow, eventTargetUrl string) error { - retryErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - var err error - evt := workflowdef.NewWorkflowDefinitionAvailabilityEvent(workflow, workflowdef.SonataFlowOperatorSource, properties.GetWorkflowEndpointUrlWithNameAndNamespace(workflow.Name, workflow.Namespace), false) - ctx, cancel := context.WithTimeout(context.Background(), constants.EventDeliveryTimeout) - defer cancel() - - if err = utils.SendCloudEventWithContext(evt, ctx, eventTargetUrl); err != nil { - // controller handles to program a new notification based on the remainder FinalizerAttempts if needed. - return fmt.Errorf("failed to send workflow definition status update event: %v", err) - } - - wfName := workflow.Name - wfNamespace := workflow.Namespace - refreshedWorkflow := &operatorapi.SonataFlow{} - if err = cli.Get(context.Background(), types.NamespacedName{Name: wfName, Namespace: wfNamespace}, refreshedWorkflow); err != nil { - if errors.IsNotFound(err) { - // workflow could have been removed after a previous notification or recon cycle. - klog.V(log.D).Infof("Workflow %s/%s was already removed, no need to retry and mark the the Status.FinalizerSucceed field.", wfName, wfNamespace) - return nil - } - return err - } - refreshedWorkflow.Status.FinalizerSucceed = true - if err = cli.Status().Update(context.Background(), refreshedWorkflow); err != nil { - if errors.IsNotFound(err) { - // workflow could have been removed after a previous notification or recon cycle. - klog.V(log.D).Infof("Workflow %s/%s was already removed, no need to retry to save the Status field.", wfName, wfNamespace) - return nil - } - return err - } - return nil - }) - return retryErr -} - -func (r *SonataFlowReconciler) cleanupTriggers(ctx context.Context, workflow *operatorapi.SonataFlow) error { - for _, triggerRef := range workflow.Status.Triggers { - trigger := &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: triggerRef.Name, - Namespace: triggerRef.Namespace, - }, - } - if err := r.Client.Delete(ctx, trigger); err != nil && !errors.IsNotFound(err) { - return err - } - } - controllerutil.RemoveFinalizer(workflow, constants.TriggerFinalizer) - return r.Client.Update(ctx, workflow) -} - -// Delete implements a handler for the Delete event. -func (r *SonataFlowReconciler) Delete(e event.DeleteEvent) error { - return nil -} - -func platformEnqueueRequestsFromMapFunc(c client.Client, p *operatorapi.SonataFlowPlatform) []reconcile.Request { - var requests []reconcile.Request - - if p.Status.IsReady() { - list := &operatorapi.SonataFlowList{} - - // Do global search in case of global operator (it may be using a global platform) - var opts []client.ListOption - if !platform.IsCurrentOperatorGlobal() { - opts = append(opts, client.InNamespace(p.Namespace)) - } - - if err := c.List(context.Background(), list, opts...); err != nil { - klog.V(log.E).ErrorS(err, "Failed to list workflows") - return requests - } - - for _, workflow := range list.Items { - cond := workflow.Status.GetTopLevelCondition() - if cond.IsFalse() && api.WaitingForPlatformReason == cond.Reason { - klog.V(log.I).InfoS("Platform ready, wake-up workflow", "platform", p.Name, "workflow", workflow.Name) - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: workflow.Namespace, - Name: workflow.Name, - }, - }) - } - } - } - return requests -} - -func buildEnqueueRequestsFromMapFunc(c client.Client, b *operatorapi.SonataFlowBuild) []reconcile.Request { - var requests []reconcile.Request - - if b.Status.BuildPhase == operatorapi.BuildPhaseSucceeded { - // Fetch the Workflow instance - workflow := &operatorapi.SonataFlow{} - namespacedName := types.NamespacedName{ - Namespace: workflow.Namespace, - Name: workflow.Name, - } - err := c.Get(context.Background(), namespacedName, workflow) - if err != nil { - if errors.IsNotFound(err) { - return requests - } - klog.V(log.I).ErrorS(err, "Failed to get SonataFlow") - return requests - } - - if workflow.Status.IsBuildRunningOrUnknown() { - klog.V(log.I).InfoS("Build %s ready, wake-up workflow: %s", b.Name, workflow.Name) - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: workflow.Namespace, - Name: workflow.Name, - }, - }) - } - - } - return requests -} - -// SetupWithManager sets up the controller with the Manager. -func (r *SonataFlowReconciler) SetupWithManager(mgr ctrl.Manager) error { - builder := ctrl.NewControllerManagedBy(mgr). - For(&operatorapi.SonataFlow{}). - Owns(&appsv1.Deployment{}). - Owns(&v1.PodDisruptionBudget{}). - Owns(&corev1.Service{}). - Owns(&corev1.ConfigMap{}). - Owns(&operatorapi.SonataFlowBuild{}). - Watches(&operatorapi.SonataFlowPlatform{}, handler.EnqueueRequestsFromMapFunc(func(c context.Context, a client.Object) []reconcile.Request { - plat, ok := a.(*operatorapi.SonataFlowPlatform) - if !ok { - klog.V(log.E).InfoS("Failed to retrieve workflow list. Type assertion failed", "assertion", a) - return []reconcile.Request{} - } - return platformEnqueueRequestsFromMapFunc(mgr.GetClient(), plat) - })). - Watches(&operatorapi.SonataFlowBuild{}, handler.EnqueueRequestsFromMapFunc(func(c context.Context, a client.Object) []reconcile.Request { - build, ok := a.(*operatorapi.SonataFlowBuild) - if !ok { - klog.V(log.I).ErrorS(fmt.Errorf("type assertion failed: %v", a), "Failed to retrieve workflow list") - return []reconcile.Request{} - } - return buildEnqueueRequestsFromMapFunc(mgr.GetClient(), build) - })). - Watches(&autoscalingv2.HorizontalPodAutoscaler{}, handler.EnqueueRequestsFromMapFunc(r.mapHPAToSonataFlowRequests), pkgbuilder.WithPredicates(hpaToSonataFlowPredicate())) - - knativeAvail, err := knative.GetKnativeAvailability(mgr.GetConfig()) - if err != nil { - return err - } - if knativeAvail.Serving { - builder = builder.Owns(&servingv1.Service{}) - } - if knativeAvail.Eventing { - builder = builder.Owns(&eventingv1.Trigger{}). - Owns(&sourcesv1.SinkBinding{}). - Watches(&eventingv1.Trigger{}, handler.EnqueueRequestsFromMapFunc(knative.MapTriggerToPlatformRequests)) - } - promAvail, err := monitoring.GetPrometheusAvailability(mgr.GetConfig()) - if err != nil { - return err - } - if promAvail { - builder = builder.Owns(&prometheus.ServiceMonitor{}) - } - - return builder.Complete(r) -} - -// hpaToSonataFlowPredicate filters the HorizontalPodAutoscaler events that might require attention by the SonataFlow -// controller, i.e., those HorizontalPodAutoscalers that points to a SonataFlow and has relevant changes rather than -// status updates. Note that changes in such HorizontalPodAutoscaler might for example have impact on the potentially -// generated PodDisruptionBudget. -func hpaToSonataFlowPredicate() predicate.Funcs { - return predicate.Funcs{ - CreateFunc: func(e ctrlevent.CreateEvent) bool { - return kubernetes.IsHPAndTargetsASonataFlowAsBool(e.Object) - }, - UpdateFunc: func(e ctrlevent.UpdateEvent) bool { - oldHpa, oldHpaOk := kubernetes.IsHPAndTargetsASonataFlow(e.ObjectOld) - newHpa, newHpaOK := kubernetes.IsHPAndTargetsASonataFlow(e.ObjectNew) - if oldHpaOk || newHpaOK { - return !kubernetes.HPAEqualsBySpec(oldHpa, newHpa) - } - return false - }, - DeleteFunc: func(e ctrlevent.DeleteEvent) bool { - return kubernetes.IsHPAndTargetsASonataFlowAsBool(e.Object) - }, - GenericFunc: func(e ctrlevent.GenericEvent) bool { - return kubernetes.IsHPAndTargetsASonataFlowAsBool(e.Object) - }, - } -} - -// mapHPAToSonataFlowRequests given a HorizontalPodAutoscaler that targets a SonataFlow, returns the recon request to -// that workflow. -func (r *SonataFlowReconciler) mapHPAToSonataFlowRequests(ctx context.Context, object client.Object) []reconcile.Request { - hpa := object.(*autoscalingv2.HorizontalPodAutoscaler) - return []reconcile.Request{ - { - NamespacedName: types.NamespacedName{ - Namespace: hpa.Namespace, - Name: hpa.Spec.ScaleTargetRef.Name, - }, - }, - } -} diff --git a/internal/controller/sonataflow_controller_test.go b/internal/controller/sonataflow_controller_test.go deleted file mode 100644 index db13af0e..00000000 --- a/internal/controller/sonataflow_controller_test.go +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "testing" - - "k8s.io/client-go/rest" - - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/api" - - "github.com/kubesmarts/logic-operator/test" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func TestSonataFlowControllerAddsFinalizerReplicasAndSelector(t *testing.T) { - t.Run("verify that workflow finalizer, replicas and selector are early added are if missing", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlow object with metadata and spec. - ksw := test.GetBaseSonataFlow(namespace) - // The Workflow controller needs at least to perform a call for Platforms, so we need to add this kind to the known - // ones by the fake client - ksp := test.GetBasePlatformInReadyPhase(namespace) - // Objects to track in the fake Client. - objs := []runtime.Object{ksw, ksp} - - // Create a fake client to mock API calls. - cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(objs...).WithStatusSubresource(ksw, ksp).Build() - // Create a SonataFlowReconciler object with the scheme and fake client. - r := &SonataFlowReconciler{Client: cl, Scheme: cl.Scheme(), Config: &rest.Config{}, Recorder: test.NewFakeRecorder()} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksw.Name, - Namespace: ksw.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - afterReconcileWorkflow := &v1alpha08.SonataFlow{} - if err := cl.Get(context.TODO(), req.NamespacedName, afterReconcileWorkflow); err != nil { - t.Fatalf("Failed to fetch supposed to exist workflow %v", err) - } - // finalizer and replicas must have been set. - assert.NotNil(t, afterReconcileWorkflow.Spec.PodTemplate.Replicas) - assert.Equal(t, int32(1), *afterReconcileWorkflow.Spec.PodTemplate.Replicas) - assert.Equal(t, []string{"workflow-deletion"}, afterReconcileWorkflow.GetFinalizers()) - - _, err = r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - if err := cl.Get(context.TODO(), req.NamespacedName, afterReconcileWorkflow); err != nil { - t.Fatalf("Failed to fetch supposed to exist workflow %v", err) - } - // status scale selector must have been set. - expectedSelector := "app=greeting,app.kubernetes.io/component=serverless-workflow,app.kubernetes.io/instance=greeting,app.kubernetes.io/managed-by=sonataflow-operator,app.kubernetes.io/name=greeting,app.kubernetes.io/version=main,sonataflow.org/workflow-app=greeting,sonataflow.org/workflow-namespace=TestSonataFlowControllerAddsFinalizerReplicasAndSelector/verify_that_workflow_finalizer,_replicas_and_selector_are_early_added_are_if_missing" - assert.Equal(t, expectedSelector, afterReconcileWorkflow.Status.Selector) - }) -} - -func TestSonataFlowController(t *testing.T) { - t.Run("verify that a basic reconcile is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlow object with metadata and spec. - ksw := test.GetBaseSonataFlow(namespace) - replicas := int32(2) - ksw.Spec.PodTemplate.Replicas = &replicas - ksw.SetFinalizers([]string{"workflow-deletion"}) - ksw.Status.Selector = "current-selector" - // The Workflow controller needs at least to perform a call for Platforms, so we need to add this kind to the known - // ones by the fake client - ksp := test.GetBasePlatformInReadyPhase(namespace) - // Objects to track in the fake Client. - objs := []runtime.Object{ksw, ksp} - - // Create a fake client to mock API calls. - cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(objs...).WithStatusSubresource(ksw, ksp).Build() - // Create a SonataFlowReconciler object with the scheme and fake client. - r := &SonataFlowReconciler{Client: cl, Scheme: cl.Scheme(), Config: &rest.Config{}, Recorder: test.NewFakeRecorder()} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksw.Name, - Namespace: ksw.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - afterReconcileWorkflow := &v1alpha08.SonataFlow{} - if err := cl.Get(context.TODO(), req.NamespacedName, afterReconcileWorkflow); err != nil { - t.Fatalf("Failed to fetch supposed to exist workflow %v", err) - } - // Perform some checks on the created CR - // finalizers, replicas and selector remained untouched. - assert.Equal(t, int32(2), *afterReconcileWorkflow.Spec.PodTemplate.Replicas) - assert.Equal(t, []string{"workflow-deletion"}, afterReconcileWorkflow.GetFinalizers()) - assert.Equal(t, "current-selector", afterReconcileWorkflow.Status.Selector) - - assert.True(t, afterReconcileWorkflow.Spec.Flow.Start.StateName == "ChooseOnLanguage") - // We create the initial build and return - assert.True(t, afterReconcileWorkflow.Status.GetCondition(api.BuiltConditionType).IsFalse()) - assert.True(t, afterReconcileWorkflow.Status.GetCondition(api.RunningConditionType).IsFalse()) - assert.True(t, afterReconcileWorkflow.Status.IsWaitingForBuild()) - assert.True(t, len(afterReconcileWorkflow.Spec.Flow.States) == 4) - - assert.True(t, ksw.Spec.Flow.Start.StateName == "ChooseOnLanguage") - assert.True(t, len(ksw.Spec.Flow.States) == 4) - - assert.Equal(t, ksp.Name, afterReconcileWorkflow.Status.Platform.Name) - assert.Equal(t, ksp.Namespace, afterReconcileWorkflow.Status.Platform.Namespace) - }) -} diff --git a/internal/controller/sonataflowbuild_controller.go b/internal/controller/sonataflowbuild_controller.go deleted file mode 100644 index 53d3ba97..00000000 --- a/internal/controller/sonataflowbuild_controller.go +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - "reflect" - "time" - - "k8s.io/klog/v2" - - "github.com/kubesmarts/logic-operator/internal/controller/workflows" - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" - - buildv1 "github.com/openshift/api/build/v1" - imgv1 "github.com/openshift/api/image/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/utils" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/builder" - "github.com/kubesmarts/logic-operator/log" -) - -// SonataFlowBuildReconciler reconciles a SonataFlowBuild object -type SonataFlowBuildReconciler struct { - client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Config *rest.Config -} - -const ( - requeueAfterForNewBuild = 10 * time.Second - requeueAfterForBuildRunning = 30 * time.Second -) - -// +kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowbuilds,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowbuilds/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowbuilds/finalizers,verbs=update - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// the SonataFlowBuild object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.1/pkg/reconcile -func (r *SonataFlowBuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - build := &operatorapi.SonataFlowBuild{} - err := r.Client.Get(ctx, req.NamespacedName, build) - if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - klog.V(log.E).ErrorS(err, "Failed to get the SonataFlowBuild") - return ctrl.Result{}, err - } - - phase := build.Status.BuildPhase - buildManager, err := builder.NewBuildManager(ctx, r.Client, r.Config, build.Name, build.Namespace) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to get create a build manager to handle the workflow build") - return ctrl.Result{}, err - } - - if phase == operatorapi.BuildPhaseNone || kubeutil.GetAnnotationAsBool(build, operatorapi.BuildRestartAnnotation) { - return r.scheduleNewBuild(ctx, buildManager, build) - } else if phase != operatorapi.BuildPhaseSucceeded && phase != operatorapi.BuildPhaseError && phase != operatorapi.BuildPhaseFailed { - beforeReconcileStatus := build.Status.DeepCopy() - if err = buildManager.Reconcile(build); err != nil { - return ctrl.Result{}, err - } - if !reflect.DeepEqual(build.Status, beforeReconcileStatus) { - if err = r.manageStatusUpdate(ctx, build, beforeReconcileStatus.BuildPhase); err != nil { - return ctrl.Result{}, err - } - } - return ctrl.Result{RequeueAfter: requeueAfterForBuildRunning}, nil - } - - return ctrl.Result{}, nil -} - -func (r *SonataFlowBuildReconciler) scheduleNewBuild(ctx context.Context, buildManager builder.BuildManager, build *operatorapi.SonataFlowBuild) (ctrl.Result, error) { - if err := buildManager.Schedule(build); err != nil { - return ctrl.Result{}, err - } - if err := r.manageStatusUpdate(ctx, build, ""); err != nil { - return ctrl.Result{}, err - } - if kubeutil.GetAnnotationAsBool(build, operatorapi.BuildRestartAnnotation) { - // Remove restart annotation to not enter in infinity reconciliation loop - kubeutil.SetAnnotation(build, operatorapi.BuildRestartAnnotation, "false") - if err := r.Update(ctx, build); err != nil { - return ctrl.Result{}, err - } - // Signals to the workflow that we are rebuilding - workflowManager, err := workflows.NewManager(r.Client, ctx, build.Namespace, build.Name) - if err != nil { - return ctrl.Result{}, err - } - if err := workflowManager.SetBuiltStatusToRunning("Build marked to restart"); err != nil { - return ctrl.Result{}, err - } - } - - return ctrl.Result{RequeueAfter: requeueAfterForNewBuild}, nil -} - -func (r *SonataFlowBuildReconciler) manageStatusUpdate(ctx context.Context, instance *operatorapi.SonataFlowBuild, beforeReconcilePhase operatorapi.BuildPhase) error { - err := r.Status().Update(ctx, instance) - // Don't need to spam events if the phase hasn't changed - if err == nil && beforeReconcilePhase != instance.Status.BuildPhase { - r.Recorder.Event(instance, corev1.EventTypeNormal, "Updated", fmt.Sprintf("Updated buildphase to %s", instance.Status.BuildPhase)) - } - return err -} - -// SetupWithManager sets up the controller with the Manager. -func (r *SonataFlowBuildReconciler) SetupWithManager(mgr ctrl.Manager) error { - if utils.IsOpenShift() { - return ctrl.NewControllerManagedBy(mgr). - For(&operatorapi.SonataFlowBuild{}). - Owns(&buildv1.BuildConfig{}). - Owns(&imgv1.ImageStream{}). - Complete(r) - } - return ctrl.NewControllerManagedBy(mgr). - For(&operatorapi.SonataFlowBuild{}). - Complete(r) -} diff --git a/internal/controller/sonataflowbuild_controller_test.go b/internal/controller/sonataflowbuild_controller_test.go deleted file mode 100644 index 1cce406a..00000000 --- a/internal/controller/sonataflowbuild_controller_test.go +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/container-builder/api" - "github.com/kubesmarts/logic-operator/test" -) - -func TestSonataFlowBuildController(t *testing.T) { - namespace := t.Name() - ksw := test.GetBaseSonataFlow(namespace) - ksb := test.GetNewEmptySonataFlowBuild(ksw.Name, namespace) - - cl := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(ksb, ksw). - WithRuntimeObjects(test.GetBasePlatformInReadyPhase(namespace)). - WithRuntimeObjects(test.GetSonataFlowBuilderConfig(namespace)). - WithStatusSubresource(ksb, ksw). - Build() - - r := &SonataFlowBuildReconciler{cl, cl.Scheme(), &record.FakeRecorder{}, &rest.Config{}} - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksb.Name, - Namespace: ksb.Namespace, - }, - } - - result, err := r.Reconcile(context.TODO(), req) - assert.NoError(t, err) - assert.Equal(t, requeueAfterForNewBuild, result.RequeueAfter) - - // verify if the inner build has been persisted correctly - assert.NoError(t, cl.Get(context.TODO(), req.NamespacedName, ksb)) - assert.Equal(t, operatorapi.BuildPhaseScheduling, ksb.Status.BuildPhase) - assert.NotNil(t, ksb.Status.InnerBuild) - - containerBuild := &api.ContainerBuild{} - assert.NoError(t, ksb.Status.GetInnerBuild(containerBuild)) - assert.Equal(t, string(ksb.Status.BuildPhase), string(containerBuild.Status.Phase)) -} - -func TestSonataFlowBuildController_WithArgsAndEnv(t *testing.T) { - namespace := t.Name() - ksw := test.GetBaseSonataFlow(namespace) - ksb := test.GetNewEmptySonataFlowBuild(ksw.Name, namespace) - - ksb.Spec.Arguments = make([]string, 1) - ksb.Spec.Arguments[0] = "--build-args=MYENV=VALUE" - ksb.Spec.Envs = make([]v1.EnvVar, 1) - ksb.Spec.Envs[0] = v1.EnvVar{ - Name: "QUARKUS_EXTENSIONS", - Value: "extension1,extension2", - } - - cl := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(ksb, ksw). - WithRuntimeObjects(test.GetBasePlatformInReadyPhase(namespace)). - WithRuntimeObjects(test.GetSonataFlowBuilderConfig(namespace)). - WithStatusSubresource(ksb, ksw). - Build() - - r := &SonataFlowBuildReconciler{cl, cl.Scheme(), &record.FakeRecorder{}, &rest.Config{}} - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksb.Name, - Namespace: ksb.Namespace, - }, - } - - result, err := r.Reconcile(context.TODO(), req) - assert.NoError(t, err) - assert.Equal(t, requeueAfterForNewBuild, result.RequeueAfter) - - assert.NoError(t, cl.Get(context.TODO(), req.NamespacedName, ksb)) - assert.Equal(t, operatorapi.BuildPhaseScheduling, ksb.Status.BuildPhase) - assert.NotNil(t, ksb.Status.InnerBuild) - - containerBuild := &api.ContainerBuild{} - assert.NoError(t, ksb.Status.GetInnerBuild(containerBuild)) - assert.Equal(t, string(ksb.Status.BuildPhase), string(containerBuild.Status.Phase)) - assert.Len(t, containerBuild.Spec.Tasks[0].Kaniko.AdditionalFlags, 1) - assert.Len(t, containerBuild.Spec.Tasks[0].Kaniko.Envs, 1) -} - -func TestSonataFlowBuildController_MarkToRestart(t *testing.T) { - namespace := t.Name() - ksw := test.GetBaseSonataFlow(namespace) - ksb := test.GetNewEmptySonataFlowBuild(ksw.Name, namespace) - ksb.Annotations = map[string]string{operatorapi.BuildRestartAnnotation: "true"} - - cl := test.NewSonataFlowClientBuilder(). - WithRuntimeObjects(ksb, ksw). - WithRuntimeObjects(test.GetBasePlatformInReadyPhase(namespace)). - WithRuntimeObjects(test.GetSonataFlowBuilderConfig(namespace)). - WithStatusSubresource(ksb, ksw). - Build() - - r := &SonataFlowBuildReconciler{cl, cl.Scheme(), &record.FakeRecorder{}, &rest.Config{}} - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksb.Name, - Namespace: ksb.Namespace, - }, - } - - _, err := r.Reconcile(context.TODO(), req) - assert.NoError(t, err) - ksb = test.MustGetBuild(t, cl, types.NamespacedName{Name: ksb.Name, Namespace: namespace}) - assert.Equal(t, "false", ksb.Annotations[operatorapi.BuildRestartAnnotation]) -} diff --git a/internal/controller/sonataflowclusterplatform_controller.go b/internal/controller/sonataflowclusterplatform_controller.go deleted file mode 100644 index ba3356db..00000000 --- a/internal/controller/sonataflowclusterplatform_controller.go +++ /dev/null @@ -1,176 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - "time" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/klog/v2" - ctrlrun "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - clientr "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/internal/controller/clusterplatform" - "github.com/kubesmarts/logic-operator/log" -) - -// SonataFlowClusterPlatformReconciler reconciles a SonataFlowClusterPlatform object -type SonataFlowClusterPlatformReconciler struct { - // This Client, initialized using mgr.Client() above, is a split Client - // that reads objects from the cache and writes to the API server - ctrl.Client - // Non-caching Client - Reader ctrl.Reader - Scheme *runtime.Scheme - Config *rest.Config - Recorder record.EventRecorder -} - -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowclusterplatforms,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowclusterplatforms/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowclusterplatforms/finalizers,verbs=update - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// TODO(user): Modify the Reconcile function to compare the state specified by -// the SonataFlowClusterPlatform object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.13.0/pkg/reconcile -func (r *SonataFlowClusterPlatformReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { - - // Fetch the SonataFlowClusterPlatform instance - var instance operatorapi.SonataFlowClusterPlatform - - err := r.Client.Get(ctx, req.NamespacedName, &instance) - if err != nil { - if errors.IsNotFound(err) { - return reconcile.Result{}, nil - } - klog.V(log.E).ErrorS(err, "Failed to get SonataFlowClusterPlatform") - return reconcile.Result{}, err - } - - instance.Status.Manager().InitializeConditions() - - cli, _ := clientr.FromCtrlClientSchemeAndConfig(r.Client, r.Scheme, r.Config) - action := clusterplatform.NewInitializeAction() - action.InjectClient(cli) - klog.V(log.I).InfoS("Invoking action", "Name", action.Name()) - - target := instance.DeepCopy() - - if action.CanHandle(ctx, target) { - if err = action.Handle(ctx, target); err != nil { - target.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformFailureReason, err.Error()) - if err := r.Client.Status().Patch(ctx, target, ctrl.MergeFrom(&instance)); err != nil { - return reconcile.Result{}, err - } - r.Recorder.Event(&instance, corev1.EventTypeWarning, "Failed", fmt.Sprintf("Failed to update SonataFlowClusterPlaform: %s", err)) - return reconcile.Result{}, err - } - - if target != nil { - target.Status.ObservedGeneration = instance.Generation - - if err := r.Client.Status().Patch(ctx, target, ctrl.MergeFrom(&instance)); err != nil { - r.Recorder.Event(&instance, corev1.EventTypeNormal, "Status Updated", fmt.Sprintf("Updated cluster platform condition %s", instance.Status.GetTopLevelCondition())) - return reconcile.Result{}, err - } - } - - // handle one action at time so the resource - // is always at its latest state - r.Recorder.Event(&instance, corev1.EventTypeNormal, "Updated", fmt.Sprintf("Updated cluster platform condition to %s", instance.Status.GetTopLevelCondition())) - - if target != nil && target.Status.IsReady() { - return reconcile.Result{}, nil - } - - // Requeue - return reconcile.Result{ - RequeueAfter: 5 * time.Second, - }, nil - } - - return reconcile.Result{}, nil -} - -// SetupWithManager sets up the controller with the Manager. -func (r *SonataFlowClusterPlatformReconciler) SetupWithManager(mgr ctrlrun.Manager) error { - return ctrlrun.NewControllerManagedBy(mgr). - For(&operatorapi.SonataFlowClusterPlatform{}). - Watches(&operatorapi.SonataFlowPlatform{}, handler.EnqueueRequestsFromMapFunc(r.mapPlatformToClusterPlatformRequests)). - Watches(&operatorapi.SonataFlowClusterPlatform{}, handler.EnqueueRequestsFromMapFunc(r.mapClusterPlatformToClusterPlatformRequests)). - Complete(r) -} - -// if actively referenced sonataflowplatform object is changed, reconcile the active SonataFlowClusterPlatform. -func (r *SonataFlowClusterPlatformReconciler) mapPlatformToClusterPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) - if err != nil && !errors.IsNotFound(err) { - klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") - return nil - } - - if sfcPlatform != nil { - sfpcRefNsName := types.NamespacedName{Namespace: sfcPlatform.Spec.PlatformRef.Namespace, Name: sfcPlatform.Spec.PlatformRef.Name} - if client.ObjectKeyFromObject(object) == sfpcRefNsName { - return []reconcile.Request{{NamespacedName: client.ObjectKeyFromObject(sfcPlatform)}} - } - } - return nil -} - -// if active sonataflowclusterplatform is changed, reconcile other SonataFlowClusterPlatforms. -func (r *SonataFlowClusterPlatformReconciler) mapClusterPlatformToClusterPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - sfcPlatform := object.(*operatorapi.SonataFlowClusterPlatform) - var requests []reconcile.Request - if sfcPlatform != nil && clusterplatform.IsActive(sfcPlatform) { - var scpList operatorapi.SonataFlowClusterPlatformList - if err := r.List(ctx, &scpList); err != nil { - klog.V(log.E).ErrorS(err, "Could not list SonataFlowClusterPlatforms. "+ - "SonataFlowClusterPlatforms affected by changes to the active SonataFlowClusterPlatform %s will not be reconciled.", - sfcPlatform.Name) - return nil - } - - scpNamespacedName := client.ObjectKeyFromObject(sfcPlatform) - for _, cPlatform := range scpList.Items { - namespacedName := client.ObjectKeyFromObject(&cPlatform) - // this check is required so that the active clusterplatform object doesn't reconcile - if scpNamespacedName != namespacedName { - requests = append(requests, reconcile.Request{NamespacedName: namespacedName}) - } - } - } - return requests -} diff --git a/internal/controller/sonataflowplatform_controller.go b/internal/controller/sonataflowplatform_controller.go deleted file mode 100644 index 60808c4b..00000000 --- a/internal/controller/sonataflowplatform_controller.go +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "fmt" - "strings" - "time" - - autoscalingv2 "k8s.io/api/autoscaling/v2" - pkgbuilder "sigs.k8s.io/controller-runtime/pkg/builder" - ctrlevent "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/predicate" - - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - - "github.com/kubesmarts/logic-operator/internal/controller/knative" - "github.com/kubesmarts/logic-operator/internal/controller/monitoring" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/klog/v2" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - ctrlrun "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - clientr "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/internal/controller/clusterplatform" - "github.com/kubesmarts/logic-operator/internal/controller/platform" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/log" - - kubeutil "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -// SonataFlowPlatformReconciler reconciles a SonataFlowPlatform object -type SonataFlowPlatformReconciler struct { - // This Client, initialized using mgr.Client() above, is a split Client - // that reads objects from the cache and writes to the API server - ctrl.Client - // Non-caching Client - Reader ctrl.Reader - Scheme *runtime.Scheme - Config *rest.Config - Recorder record.EventRecorder -} - -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowplatforms,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowplatforms/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=sonataflow.org,resources=sonataflowplatforms/finalizers,verbs=update -//+kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=get;list;watch -//+kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;create;update;patch;delete - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// the SonataFlowPlatform object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.1/pkg/reconcile -func (r *SonataFlowPlatformReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { - // Make sure the operator is allowed to act on namespace - if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.Reader, req.Namespace); err != nil { - return reconcile.Result{}, err - } else if !ok { - klog.V(log.I).InfoS("Ignoring request because the operator hasn't got the permissions to work on namespace", "namespace", req.Namespace) - return reconcile.Result{}, nil - } - - // Fetch the Platform instance - var instance operatorapi.SonataFlowPlatform - - if err := r.Reader.Get(ctx, req.NamespacedName, &instance); err != nil { - if errors.IsNotFound(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 - return reconcile.Result{}, nil - } - // Error reading the object - requeue the request. - return reconcile.Result{}, err - } - - instance.Status.Manager().InitializeConditions() - - // Only process resources assigned to the operator - if !platform.IsOperatorHandlerConsideringLock(ctx, r.Reader, req.Namespace, &instance) { - klog.V(log.I).InfoS("Ignoring request because resource is not assigned to current operator") - return reconcile.Result{}, nil - } - actions := []platform.Action{ - platform.NewInitializeAction(), - platform.NewServiceAction(), - platform.NewWarmAction(r.Reader), - platform.NewCreateAction(), - platform.NewMonitorAction(), - } - - var err error - - target := instance.DeepCopy() - - if err = r.updateIfActiveClusterPlatformExists(ctx, req, target); err != nil { - return reconcile.Result{}, err - } - - // If the platform is being deleted, clean up the triggers on a different namespace - if instance.DeletionTimestamp != nil && controllerutil.ContainsFinalizer(&instance, constants.TriggerFinalizer) { - err := r.cleanupTriggers(ctx, &instance) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to clean up triggers for platform %s in namespace %s", instance.Name, instance.Namespace) - return reconcile.Result{}, err - } - return reconcile.Result{}, nil - } - - if monitoring.IsMonitoringEnabled(&instance) { - monitoringAvail, err := monitoring.GetPrometheusAvailability(r.Config) - if err != nil { - return reconcile.Result{}, err - } - if !monitoringAvail { - r.Recorder.Event(&instance, corev1.EventTypeWarning, "PrometheusNotAvailable", fmt.Sprintf("Monitoring is enabled in platform %s, but Prometheus is not installed", instance.Name)) - } - } - - for _, a := range actions { - cli, _ := clientr.FromCtrlClientSchemeAndConfig(r.Client, r.Scheme, r.Config) - a.InjectClient(cli) - - if a.CanHandle(target) { - - klog.V(log.I).InfoS("Invoking action", "Name", a.Name()) - - target, event, err := a.Handle(ctx, target) - if event != nil { - r.Recorder.Event(&instance, event.Type, event.Reason, event.Message) - } - if err != nil { - if target != nil { - target.Status.Manager().MarkFalse(api.SucceedConditionType, operatorapi.PlatformFailureReason, err.Error()) - if err = platform.SafeUpdatePlatformStatus(ctx, target); err != nil { - return reconcile.Result{}, err - } - } - r.Recorder.Event(&instance, corev1.EventTypeWarning, "Failed", fmt.Sprintf("Failed to update SonataFlowPlaform: %s", err)) - return reconcile.Result{}, err - } - - if target != nil { - target.Status.ObservedGeneration = instance.Generation - if err = platform.SafeUpdatePlatform(ctx, target); err != nil { - return reconcile.Result{}, err - } - - err = platform.SafeUpdatePlatformStatus(ctx, target) - if err != nil { - return reconcile.Result{}, err - } - } else { - return reconcile.Result{ - RequeueAfter: 5 * time.Second, - }, nil - } - - // handle one action at time so the resource - // is always at its latest state - r.Recorder.Event(&instance, corev1.EventTypeNormal, "Updated", fmt.Sprintf("Updated platform condition to %s", instance.Status.GetTopLevelCondition())) - break - } - } - - if target != nil && target.Status.IsReady() { - return reconcile.Result{}, nil - } - - // Requeue - return reconcile.Result{ - RequeueAfter: 5 * time.Second, - }, nil - -} - -func (r *SonataFlowPlatformReconciler) cleanupTriggers(ctx context.Context, platform *operatorapi.SonataFlowPlatform) error { - for _, triggerRef := range platform.Status.Triggers { - trigger := &eventingv1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: triggerRef.Name, - Namespace: triggerRef.Namespace, - }, - } - if err := r.Client.Delete(ctx, trigger); err != nil && !errors.IsNotFound(err) { - return err - } - } - controllerutil.RemoveFinalizer(platform, constants.TriggerFinalizer) - return r.Client.Update(ctx, platform) -} - -// sonataFlowPlatformUpdateStatus If an active cluster platform exists, update platform.Status accordingly -func (r *SonataFlowPlatformReconciler) updateIfActiveClusterPlatformExists(ctx context.Context, req reconcile.Request, target *operatorapi.SonataFlowPlatform) error { - // Fetch the active SonataFlowClusterPlatform instance - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) - if err != nil && !errors.IsNotFound(err) { - klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") - return err - } - - if sfcPlatform != nil { - sfPlatform := &operatorapi.SonataFlowPlatform{} - - platformRef := sfcPlatform.Spec.PlatformRef - namespacedName := types.NamespacedName{Namespace: platformRef.Namespace, Name: platformRef.Name} - if req.NamespacedName == namespacedName { - sfPlatform = target.DeepCopy() - } else { - // retrieve referenced platform object - err := r.Reader.Get(ctx, namespacedName, sfPlatform) - if err != nil && !errors.IsNotFound(err) { - klog.V(log.E).ErrorS(err, "Failed to get referenced SonataFlowPlatform", namespacedName) - return err - } - } - - target.Status.ClusterPlatformRef = &operatorapi.SonataFlowClusterPlatformRefStatus{ - Name: sfcPlatform.Name, - PlatformRef: operatorapi.SonataFlowPlatformRef{ - Name: platformRef.Name, - Namespace: platformRef.Namespace, - }, - } - - if sfcPlatform.Spec.Capabilities != nil && contains(sfcPlatform.Spec.Capabilities.Workflows, clusterplatform.PlatformServices) { - tpsDI := services.NewDataIndexHandler(target) - tpsDI.SetServiceUrlInPlatformStatus(sfPlatform) - - tpsJS := services.NewJobServiceHandler(target) - tpsJS.SetServiceUrlInPlatformStatus(sfPlatform) - } - } else { - target.Status.ClusterPlatformRef = nil - } - - return nil -} - -// SetupWithManager sets up the controller with the Manager. -func (r *SonataFlowPlatformReconciler) SetupWithManager(mgr ctrlrun.Manager) error { - builder := ctrlrun.NewControllerManagedBy(mgr). - For(&operatorapi.SonataFlowPlatform{}). - Owns(&appsv1.Deployment{}). - Owns(&corev1.Service{}). - Owns(&corev1.ConfigMap{}). - Watches(&operatorapi.SonataFlowPlatform{}, handler.EnqueueRequestsFromMapFunc(r.mapPlatformToPlatformRequests)). - Watches(&operatorapi.SonataFlowClusterPlatform{}, handler.EnqueueRequestsFromMapFunc(r.mapClusterPlatformToPlatformRequests)). - Watches(&autoscalingv2.HorizontalPodAutoscaler{}, handler.EnqueueRequestsFromMapFunc(r.mapHPAToPlatformRequests), pkgbuilder.WithPredicates(hpaToSonataFlowPlatformServicePredicate())) - - knativeAvail, err := knative.GetKnativeAvailability(mgr.GetConfig()) - if err != nil { - return err - } - if knativeAvail.Eventing { - builder = builder.Owns(&eventingv1.Trigger{}). - Owns(&sourcesv1.SinkBinding{}). - Watches(&eventingv1.Trigger{}, handler.EnqueueRequestsFromMapFunc(knative.MapTriggerToPlatformRequests)) - } - return builder.Complete(r) -} - -// if active clusterplatform object is changed, reconcile all SonataFlowPlatforms in the cluster. -func (r *SonataFlowPlatformReconciler) mapClusterPlatformToPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - sfcPlatform := object.(*operatorapi.SonataFlowClusterPlatform) - if sfcPlatform != nil && clusterplatform.IsActive(sfcPlatform) { - return r.platformRequests(ctx, sfcPlatform, true) - } - return nil -} - -// if actively referenced sonataflowplatform is changed, reconcile other SonataFlowPlatforms in the cluster. -func (r *SonataFlowPlatformReconciler) mapPlatformToPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - sfp := object.(*operatorapi.SonataFlowPlatform) - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) - if err != nil && !errors.IsNotFound(err) { - klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") - return nil - } - - if sfcPlatform != nil { - sfpcRefNsName := types.NamespacedName{Namespace: sfcPlatform.Spec.PlatformRef.Namespace, Name: sfcPlatform.Spec.PlatformRef.Name} - if client.ObjectKeyFromObject(sfp) == sfpcRefNsName { - return r.platformRequests(ctx, sfcPlatform, false) - } - } - return nil -} - -func (r *SonataFlowPlatformReconciler) platformRequests(ctx context.Context, sfcPlatform *operatorapi.SonataFlowClusterPlatform, allPlatforms bool) []reconcile.Request { - var plList operatorapi.SonataFlowPlatformList - if err := r.List(ctx, &plList, client.InNamespace("")); err != nil { - klog.V(log.E).ErrorS(err, "could not list SonataFlowPlatforms. "+ - "SonataFlowPlatforms affected by changes to the active SonataFlowPlatform or SonataFlowClusterPlatform object will not be reconciled.") - return nil - } - - sfpcRefNsName := types.NamespacedName{Namespace: sfcPlatform.Spec.PlatformRef.Namespace, Name: sfcPlatform.Spec.PlatformRef.Name} - var requests []reconcile.Request - for _, sfp := range plList.Items { - sfpNsName := client.ObjectKeyFromObject(&sfp) - // this check is required so that the cluster-referenced platform object doesn't infinitely reconcile - if sfpNsName != sfpcRefNsName || allPlatforms { - requests = append(requests, reconcile.Request{NamespacedName: sfpNsName}) - } - } - return requests -} - -func contains(slice []operatorapi.WorkFlowCapability, s operatorapi.WorkFlowCapability) bool { - for _, a := range slice { - if a == s { - return true - } - } - return false -} - -// mapHPAToPlatformRequests determines if the referred HorizontalPodAutoscaler targets a DI service in the given namespace, -// if any. Analyses if that namespace has an SPF that manges the DI service. If that is the case, enqueues a Request to -// the SPF to give the chance to take an action if needed. We normally want to do that in situations where the -// HorizontalPodAutoscaler was removed or has changed to let the SFP controller restore back the DI replicas or manage -// a potential PodDisruptionBudget configuration accordingly. -func (r *SonataFlowPlatformReconciler) mapHPAToPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - hpa, ok := kubeutil.IsHPAndTargetsADeployment(object) - klog.V(log.D).Infof("HorizontalPodAutoscaler %s/%s with spec.ScaleTargetRef.Kind Kind: %s requires SFP controller attention.", hpa.Namespace, hpa.Name, hpa.Spec.ScaleTargetRef.Kind) - if ok { - sfp, err := platform.GetActivePlatform(ctx, r.Client, hpa.Namespace, false) - if err != nil { - klog.V(log.D).Infof("failed to get active platform in namespace: %s, %v", hpa.Namespace, err) - return nil - } - if sfp != nil { - diHandler := services.NewDataIndexHandler(sfp) - klog.V(log.D).Infof("Active platform %s/%s was found in namespace: %s, is DI enabled: %t.", sfp.Namespace, sfp.Name, hpa.Namespace, diHandler.IsServiceEnabled()) - if diHandler.IsServiceSetInSpec() && hpa.Spec.ScaleTargetRef.Name == diHandler.GetServiceName() { - klog.V(log.D).Infof("HorizontalPodAutoscaler %s/%s targets DI: %s, enqueueing request to platform.", hpa.Namespace, hpa.Name, diHandler.GetServiceName()) - return []reconcile.Request{ - { - NamespacedName: types.NamespacedName{ - Namespace: hpa.Namespace, - Name: sfp.Name, - }, - }, - } - } - } - } - return nil -} - -// hpaToSonataFlowPlatformServicePredicate returns the predicate functions to filter HorizontalPodAutoscaler events -// that might require attention from the SFP controller. -func hpaToSonataFlowPlatformServicePredicate() predicate.Funcs { - return predicate.Funcs{ - CreateFunc: func(e ctrlevent.CreateEvent) bool { - return isHPAndCandidateToTargetADataIndexDeploymentAsBool(e.Object) - }, - UpdateFunc: func(e ctrlevent.UpdateEvent) bool { - oldHpa, oldHpaOk := isHPAndCandidateToTargetADataIndexDeployment(e.ObjectOld) - newHpa, newHpaOK := isHPAndCandidateToTargetADataIndexDeployment(e.ObjectNew) - if oldHpaOk || newHpaOK { - return !kubeutil.HPAEqualsBySpec(oldHpa, newHpa) - } - return false - }, - DeleteFunc: func(e ctrlevent.DeleteEvent) bool { - return isHPAndCandidateToTargetADataIndexDeploymentAsBool(e.Object) - }, - GenericFunc: func(e ctrlevent.GenericEvent) bool { - return isHPAndCandidateToTargetADataIndexDeploymentAsBool(e.Object) - }, - } -} - -func isHPAndCandidateToTargetADataIndexDeployment(obj client.Object) (*autoscalingv2.HorizontalPodAutoscaler, bool) { - if hpa, ok := kubeutil.IsHPAndTargetsADeployment(obj); ok { - if strings.HasSuffix(hpa.Spec.ScaleTargetRef.Name, constants.DataIndexServiceName) { - return hpa, true - } - } - return nil, false -} - -func isHPAndCandidateToTargetADataIndexDeploymentAsBool(obj client.Object) bool { - _, ok := isHPAndCandidateToTargetADataIndexDeployment(obj) - return ok -} diff --git a/internal/controller/sonataflowplatform_controller_test.go b/internal/controller/sonataflowplatform_controller_test.go deleted file mode 100644 index 662d230c..00000000 --- a/internal/controller/sonataflowplatform_controller_test.go +++ /dev/null @@ -1,1057 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - duckv1 "knative.dev/pkg/apis/duck/v1" - "knative.dev/pkg/kmeta" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/clusterplatform" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/utils" -) - -var ( - envDBKind = corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - } - - envDataIndex = corev1.EnvVar{ - Name: "KOGITO_DATA_INDEX_QUARKUS_PROFILE", - Value: "http-events-support", - } -) - -func TestSonataFlowPlatformController(t *testing.T) { - t.Run("verify that a basic reconcile is performed without error", func(t *testing.T) { - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatform() - - // Create a fake client to mock API calls. - cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, v1alpha08.PlatformCreatingReason, ksp.Status.GetTopLevelCondition().Reason) - }) - - t.Run("verify that a basic reconcile with data index service & persistence is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{}, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.Nil(t, ksp.Spec.Services.DataIndex.PodTemplate.Replicas) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check data index deployment - dep := &appsv1.Deployment{} - di := services.NewDataIndexHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - env := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - } - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, env) - - // Check with persistence set - ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - ServiceRef: &v1alpha08.PostgreSQLServiceOptions{SQLServiceOptions: &v1alpha08.SQLServiceOptions{Name: "test"}}, - }} - // Ensure correct container overriding anything set in PodSpec - ksp.Spec.Services.DataIndex.PodTemplate.Container = v1alpha08.ContainerSpec{TerminationMessagePath: "testing"} - ksp.Spec.Services.DataIndex.PodTemplate.Containers = []corev1.Container{{Name: constants.DataIndexServiceName + "2", TerminationMessagePath: "testing"}} - assert.NoError(t, cl.Update(context.TODO(), ksp)) - - _, err = r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 2) - assert.Equal(t, constants.DataIndexServiceName+"2", dep.Spec.Template.Spec.Containers[0].Name) - assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[0].TerminationMessagePath) - assert.Equal(t, constants.DataIndexServiceName, dep.Spec.Template.Spec.Containers[1].Name) - assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[1].TerminationMessagePath) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[1].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Env, env) - }) - - t.Run("verify that a basic reconcile with data index service & jdbcUrl is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - var replicas int32 = 2 - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - PodTemplate: v1alpha08.PodTemplateSpec{ - Replicas: &replicas, - Container: v1alpha08.ContainerSpec{ - Command: []string{"test:latest"}, - }, - }, - }, - Source: nil, - }, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - - di := services.NewDataIndexHandler(ksp) - - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check data index deployment - dep := &appsv1.Deployment{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - env := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - } - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, env) - - // Check with persistence set - url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service" - ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - JdbcUrl: url, - }} - // Ensure correct container overriding anything set in PodSpec - ksp.Spec.Services.DataIndex.PodTemplate.PodSpec.Containers = []corev1.Container{{Name: constants.DataIndexServiceName}} - assert.NoError(t, cl.Update(context.TODO(), ksp)) - - _, err = r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - env2 := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: url, - } - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Equal(t, &replicas, dep.Spec.Replicas) - assert.Equal(t, []string{"test:latest"}, dep.Spec.Template.Spec.Containers[0].Command) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, env) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, env2) - }) - - var ( - postgreSQLPort int = 5432 - ) - t.Run("verify that persistence options are correctly reconciled when defined in the platform", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - // Check with persistence set - ksp.Spec = v1alpha08.SonataFlowPlatformSpec{ - Services: &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceOptionsSpec{ - DBMigrationStrategy: "none", - }, - }, - }, - JobService: &v1alpha08.JobServiceServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceOptionsSpec{ - DBMigrationStrategy: "none", - }, - }, - }, - }, - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"}, - ServiceRef: &v1alpha08.SQLServiceOptions{ - Name: "postgresql", - Namespace: "default", - Port: &postgreSQLPort, - DatabaseName: "sonataflow"}, - }, - }, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - dbSourceKind := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - } - dbSourceDIURL := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://postgresql.default:5432/sonataflow?currentSchema=sonataflow-platform-data-index-service", - } - dbSourceJSURL := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_JDBC_URL", - Value: "jdbc:postgresql://postgresql.default:5432/sonataflow?currentSchema=sonataflow-platform-jobs-service", - } - dbSourceJSReactiveURL := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_REACTIVE_URL", - Value: "postgresql://postgresql.default:5432/sonataflow?search_path=sonataflow-platform-jobs-service", - } - dbUsername := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "generic"}, - Key: "POSTGRESQL_USER", - }, - }, - } - dbPassword := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "generic"}, - Key: "POSTGRESQL_PASSWORD", - }, - }, - } - // Check Data Index deployment to ensure it contains references to the persistence values defined in the platform CR - dep := &appsv1.Deployment{} - di := services.NewDataIndexHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbUsername) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbPassword) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceDIURL) - - js := services.NewJobServiceHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbUsername) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbPassword) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceJSURL) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceJSReactiveURL) - }) - - t.Run("verify that persistence options are correctly reconciled when defined in the platform and overwriten in the services spec", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - // Check with persistence set - urlDI := "jdbc:postgresql://localhost:5432/database?currentSchema=data-index-service" - urlJS := "jdbc:postgresql://localhost:5432/database?currentSchema=job-service" - ksp.Spec = v1alpha08.SonataFlowPlatformSpec{ - Services: &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "dataIndex"}, - JdbcUrl: urlDI, - }, - }, - }, - }, - JobService: &v1alpha08.JobServiceServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "job"}, - JdbcUrl: urlJS, - }, - }, - }, - }, - }, - Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{ - PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"}, - ServiceRef: &v1alpha08.SQLServiceOptions{Name: "postgresql", Namespace: "default", Port: &postgreSQLPort, DatabaseName: "sonataflow"}, - }, - }, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - dbSourceKind := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_DB_KIND", - Value: constants.PersistenceTypePostgreSQL.String(), - } - dbDIUsername := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "dataIndex"}, - Key: "POSTGRESQL_USER", - }, - }, - } - dbDIPassword := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "dataIndex"}, - Key: "POSTGRESQL_PASSWORD", - }, - }, - } - dbJSUsername := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_USERNAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "job"}, - Key: "POSTGRESQL_USER", - }, - }, - } - dbJSPassword := corev1.EnvVar{ - Name: "QUARKUS_DATASOURCE_PASSWORD", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "job"}, - Key: "POSTGRESQL_PASSWORD", - }, - }, - } - // Check Data Index deployment to ensure it contains references to the persistence values defined in the platform CR - dep := &appsv1.Deployment{} - di := services.NewDataIndexHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbDIUsername) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbDIPassword) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: "QUARKUS_DATASOURCE_JDBC_URL", Value: urlDI}) - - js := services.NewJobServiceHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbJSUsername) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbJSPassword) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: "QUARKUS_DATASOURCE_JDBC_URL", Value: urlJS}) - }) - - // Job Service tests - t.Run("verify that a basic reconcile with job service & persistence is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - JobService: &v1alpha08.JobServiceServiceSpec{}, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.JobService) - assert.Nil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check data index deployment - dep := &appsv1.Deployment{} - js := services.NewJobServiceHandler(ksp) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) - - // Check with persistence set - ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - ServiceRef: &v1alpha08.PostgreSQLServiceOptions{SQLServiceOptions: &v1alpha08.SQLServiceOptions{Name: "test"}}, - }} - // Ensure correct container overriding anything set in PodSpec - ksp.Spec.Services.JobService.PodTemplate.Container = v1alpha08.ContainerSpec{TerminationMessagePath: "testing"} - ksp.Spec.Services.JobService.PodTemplate.Containers = []corev1.Container{{Name: constants.JobServiceName + "2", TerminationMessagePath: "testing"}} - assert.NoError(t, cl.Update(context.TODO(), ksp)) - - _, err = r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 2) - assert.Equal(t, constants.JobServiceName+"2", dep.Spec.Template.Spec.Containers[0].Name) - assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[0].TerminationMessagePath) - assert.Equal(t, constants.JobServiceName, dep.Spec.Template.Spec.Containers[1].Name) - assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[1].TerminationMessagePath) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[1].Image) - assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Env, envDBKind) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[1].Env, envDataIndex) - }) - - t.Run("verify that a basic reconcile with job service & jdbcUrl is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - var replicas int32 = 2 - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - JobService: &v1alpha08.JobServiceServiceSpec{ - ServiceSpec: v1alpha08.ServiceSpec{ - PodTemplate: v1alpha08.PodTemplateSpec{ - Replicas: &replicas, - Container: v1alpha08.ContainerSpec{ - Command: []string{"test:latest"}, - }, - }, - }, - }, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - js := services.NewJobServiceHandler(ksp) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.JobService) - assert.NotNil(t, ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check job service deployment - dep := &appsv1.Deployment{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) - - // Check with persistence set - url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service" - ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ - SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, - JdbcUrl: url, - }} - // Ensure correct container overriding anything set in PodSpec - ksp.Spec.Services.JobService.PodTemplate.PodSpec.Containers = []corev1.Container{{Name: constants.JobServiceName}} - assert.NoError(t, cl.Update(context.TODO(), ksp)) - - _, err = r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image) - assert.Equal(t, int32(1), *dep.Spec.Replicas) - assert.Equal(t, []string{"test:latest"}, dep.Spec.Template.Spec.Containers[0].Command) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) - }) - - t.Run("verify that a default deployment of a job and data index service will is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{}, - JobService: &v1alpha08.JobServiceServiceSpec{}, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() - utils.SetClient(cl) - di := services.NewDataIndexHandler(ksp) - js := services.NewJobServiceHandler(ksp) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.NotNil(t, ksp.Spec.Services.JobService) - assert.NotNil(t, ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check data index deployment - dep := &appsv1.Deployment{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind) - assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) - - // Check job service deployment - dep = &appsv1.Deployment{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep)) - - assert.Len(t, dep.Spec.Template.Spec.Containers, 1) - assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind) - assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) - - }) - t.Run("verify that a basic reconcile of a cluster platform is performed without error", func(t *testing.T) { - namespace := t.Name() - - // Create a SonataFlowClusterPlatform object with metadata and spec. - kscp := test.GetBaseClusterPlatformInReadyPhase(namespace) - - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ - DataIndex: &v1alpha08.DataIndexServiceSpec{}, - JobService: &v1alpha08.JobServiceServiceSpec{}, - } - ksp2 := test.GetBasePlatformInReadyPhase(namespace) - ksp2.Name = "ksp2" - - // Create a fake client to mock API calls. - cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(kscp, ksp, ksp2).WithStatusSubresource(kscp, ksp, ksp2).Build() - utils.SetClient(cl) - - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - assert.Greater(t, len(ksp2.Status.Conditions), 0) - assert.Nil(t, ksp2.Status.ClusterPlatformRef) - - // Create a SonataFlowClusterPlatformReconciler object with the scheme and fake client. - cr := &SonataFlowClusterPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - cReq := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: kscp.Name, - }, - } - _, err = cr.Reconcile(context.TODO(), cReq) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: kscp.Name}, kscp)) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.True(t, ksp.Status.IsReady()) - assert.True(t, kscp.Status.IsReady()) - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - assert.Equal(t, kscp.Name, ksp.Status.ClusterPlatformRef.Name) - assert.Equal(t, kscp.Spec.PlatformRef.Name, ksp.Status.ClusterPlatformRef.PlatformRef.Name) - assert.Equal(t, kscp.Spec.PlatformRef.Namespace, ksp.Status.ClusterPlatformRef.PlatformRef.Namespace) - assert.NotNil(t, kscp.Spec.Capabilities) - assert.Contains(t, kscp.Spec.Capabilities.Workflows, clusterplatform.PlatformServices) - - assert.NotNil(t, ksp.Status.ClusterPlatformRef) - assert.Nil(t, ksp.Status.ClusterPlatformRef.Services) - - req2 := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp2.Name, - Namespace: ksp2.Namespace, - }, - } - _, err = r.Reconcile(context.TODO(), req2) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2)) - assert.True(t, ksp2.Status.IsReady()) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef) - assert.Equal(t, kscp.Name, ksp2.Status.ClusterPlatformRef.Name) - assert.Equal(t, kscp.Spec.PlatformRef.Name, ksp2.Status.ClusterPlatformRef.PlatformRef.Name) - assert.Equal(t, kscp.Spec.PlatformRef.Namespace, ksp2.Status.ClusterPlatformRef.PlatformRef.Namespace) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef.Services) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef) - assert.NotEmpty(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef.Url) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef) - assert.NotEmpty(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef.Url) - - psDi := services.NewDataIndexHandler(ksp) - psDi2 := services.NewDataIndexHandler(ksp2) - assert.Equal(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef.Url, psDi.GetLocalServiceBaseUrl()) - assert.Equal(t, psDi.GetLocalServiceBaseUrl()+constants.KogitoProcessInstancesEventsPath, psDi2.GetServiceBaseUrl()+constants.KogitoProcessInstancesEventsPath) - psJs := services.NewJobServiceHandler(ksp) - psJs2 := services.NewJobServiceHandler(ksp2) - assert.Equal(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef.Url, psJs.GetLocalServiceBaseUrl()) - assert.Equal(t, psJs.GetLocalServiceBaseUrl()+constants.JobServiceJobEventsPath, psJs2.GetServiceBaseUrl()+constants.JobServiceJobEventsPath) - - ksp2.Spec.Services = &v1alpha08.ServicesPlatformSpec{} - - assert.NoError(t, cl.Update(context.TODO(), ksp2)) - _, err = r.Reconcile(context.TODO(), req2) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2)) - assert.True(t, ksp2.Status.IsReady()) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef) - assert.Equal(t, kscp.Spec.PlatformRef.Name, ksp2.Status.ClusterPlatformRef.PlatformRef.Name) - assert.Equal(t, kscp.Spec.PlatformRef.Namespace, ksp2.Status.ClusterPlatformRef.PlatformRef.Namespace) - assert.Nil(t, ksp2.Status.ClusterPlatformRef.Services) - - kscp.Spec.Capabilities = &v1alpha08.SonataFlowClusterPlatformCapSpec{} - assert.NoError(t, cl.Update(context.TODO(), kscp)) - _, err = cr.Reconcile(context.TODO(), cReq) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - _, err = r.Reconcile(context.TODO(), req2) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: kscp.Name}, kscp)) - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2)) - - assert.NotNil(t, kscp.Spec.Capabilities) - assert.Empty(t, kscp.Spec.Capabilities.Workflows) - assert.NotNil(t, ksp2.Status.ClusterPlatformRef) - assert.Nil(t, ksp2.Status.ClusterPlatformRef.Services) - }) - t.Run("verify that knative resources creation for job service and data index service with platform level broker is performed without error", func(t *testing.T) { - namespace := t.Name() - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformWithBrokerInReadyPhase(namespace) - broker := test.GetDefaultBroker(namespace) - brokerName := broker.Name - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp, broker).WithStatusSubresource(ksp, broker).Build() - utils.SetClient(cl) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil && err.Error() != "waiting for K_SINK injection for service sonataflow-platform-jobs-service to complete" { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Eventing) - assert.NotNil(t, ksp.Spec.Eventing.Broker) - assert.NotNil(t, ksp.Spec.Eventing.Broker.Ref) - assert.Equal(t, ksp.Spec.Eventing.Broker.Ref.Name, brokerName) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.NotNil(t, ksp.Spec.Services.JobService) - assert.NotNil(t, ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check Triggers - trigger := &eventingv1.Trigger{} - validateTrigger(t, cl, "jobs-service-create-job-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "jobs-service-delete-job-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-jobs-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "jobs-service-create-job-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-definition-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-error-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-node-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-state-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-variable-", ksp.Namespace, ksp, trigger) - - // Check SinkBinding - sinkBinding := &sourcesv1.SinkBinding{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: "sonataflow-platform-jobs-service-sb", Namespace: ksp.Namespace}, sinkBinding)) - - }) - - t.Run("verify that knative resources creation for job service and data index service with services level brokers is performed without error", func(t *testing.T) { - namespace := t.Name() - - // Create a SonataFlowPlatform object with metadata and spec. - ksp := test.GetBasePlatformWithBrokerInReadyPhase(namespace) - brokerName := "default" - brokerNameDataIndexSource := "broker-di-source" - brokerNameJobsServiceSource := "broker-jobs-source" - brokerNameJobsServiceSink := "broker-jobs-sink" - broker := test.GetDefaultBroker(namespace) - brokerDataIndexSource := test.GetDefaultBroker(namespace) - brokerDataIndexSource.Name = brokerNameDataIndexSource - brokerJobsServiceSource := test.GetDefaultBroker(namespace) - brokerJobsServiceSource.Name = brokerNameJobsServiceSource - brokerJobsServiceSink := test.GetDefaultBroker(namespace) - brokerJobsServiceSink.Name = brokerNameJobsServiceSink - - ksp.Spec.Services.DataIndex.Source = &duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: brokerNameDataIndexSource, - Namespace: namespace, - APIVersion: "eventing.knative.dev/v1", - Kind: "Broker", - }, - } - ksp.Spec.Services.JobService.Sink = &duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: brokerNameJobsServiceSink, - Namespace: namespace, - APIVersion: "eventing.knative.dev/v1", - Kind: "Broker", - }, - } - ksp.Spec.Services.JobService.Source = &duckv1.Destination{ - Ref: &duckv1.KReference{ - Name: brokerNameJobsServiceSource, - Namespace: namespace, - APIVersion: "eventing.knative.dev/v1", - Kind: "Broker", - }, - } - - // Create a fake client to mock API calls. - cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp, broker, brokerDataIndexSource, brokerJobsServiceSource, brokerJobsServiceSink).WithStatusSubresource(ksp, broker, brokerDataIndexSource, brokerJobsServiceSource, brokerJobsServiceSink).Build() - utils.SetClient(cl) - utils.SetDiscoveryClient(test.CreateFakeKnativeAndMonitoringDiscoveryClient()) - // Create a SonataFlowPlatformReconciler object with the scheme and fake client. - r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}} - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ksp.Name, - Namespace: ksp.Namespace, - }, - } - _, err := r.Reconcile(context.TODO(), req) - if err != nil && err.Error() != "waiting for K_SINK injection for service sonataflow-platform-jobs-service to complete" { - t.Fatalf("reconcile: (%v)", err) - } - - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp)) - - // Perform some checks on the created CR - assert.Equal(t, test.CommonImageRegistryAccount, ksp.Spec.Build.Config.Registry.Address) - assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) - assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.NotNil(t, ksp.Spec.Eventing) - assert.NotNil(t, ksp.Spec.Eventing.Broker) - assert.NotNil(t, ksp.Spec.Eventing.Broker.Ref) - assert.Equal(t, ksp.Spec.Eventing.Broker.Ref.Name, brokerName) - assert.NotNil(t, ksp.Spec.Services.DataIndex) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Source) - assert.NotNil(t, ksp.Spec.Services.DataIndex.Source.Ref) - assert.Equal(t, ksp.Spec.Services.DataIndex.Source.Ref.Name, brokerNameDataIndexSource) - assert.NotNil(t, ksp.Spec.Services.JobService) - assert.NotNil(t, ksp.Spec.Services.JobService.Enabled) - assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled) - assert.NotNil(t, ksp.Spec.Services.JobService.Source) - assert.NotNil(t, ksp.Spec.Services.JobService.Source.Ref) - assert.Equal(t, ksp.Spec.Services.JobService.Source.Ref.Name, brokerNameJobsServiceSource) - assert.NotNil(t, ksp.Spec.Services.JobService.Sink) - assert.NotNil(t, ksp.Spec.Services.JobService.Sink.Ref) - assert.Equal(t, ksp.Spec.Services.JobService.Sink.Ref.Name, brokerNameJobsServiceSink) - assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) - assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason) - - // Check Triggers to have the service level source used - trigger := &eventingv1.Trigger{} - validateTrigger(t, cl, "jobs-service-create-job-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameJobsServiceSource) - validateTrigger(t, cl, "jobs-service-delete-job-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameJobsServiceSource) - validateTrigger(t, cl, "data-index-jobs-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "jobs-service-create-job-", ksp.Namespace, ksp, trigger) - validateTrigger(t, cl, "data-index-process-definition-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameDataIndexSource) - validateTrigger(t, cl, "data-index-process-error-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameDataIndexSource) - validateTrigger(t, cl, "data-index-process-node-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameDataIndexSource) - validateTrigger(t, cl, "data-index-process-state-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameDataIndexSource) - validateTrigger(t, cl, "data-index-process-variable-", ksp.Namespace, ksp, trigger) - assert.Equal(t, trigger.Spec.Broker, brokerNameDataIndexSource) - - // Check SinkBinding to have the sink level source used - sinkBinding := &sourcesv1.SinkBinding{} - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: "sonataflow-platform-jobs-service-sb", Namespace: ksp.Namespace}, sinkBinding)) - assert.NotNil(t, sinkBinding.Spec.Sink) - assert.NotNil(t, sinkBinding.Spec.Sink.Ref) - assert.Equal(t, sinkBinding.Spec.Sink.Ref.Name, brokerNameJobsServiceSink) - }) -} - -func validateTrigger(t *testing.T, cl client.WithWatch, prefix string, namespace string, ksp *v1alpha08.SonataFlowPlatform, trigger *eventingv1.Trigger) { - assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: kmeta.ChildName(prefix, string(ksp.GetUID())), Namespace: namespace}, trigger)) -} diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 0f2b0d9c..3191f592 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -1,78 +1,116 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 ( + "context" + "os" "path/filepath" "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" - apiv08 "github.com/kubesmarts/logic-operator/api/v1alpha08" - //+kubebuilder:scaffold:imports + logicv1 "github.com/kubesmarts/logic-operator/api/v1" + // +kubebuilder:scaffold:imports ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment +var ( + ctx context.Context + cancel context.CancelFunc + testEnv *envtest.Environment + cfg *rest.Config + k8sClient client.Client +) -func TestAPIs(t *testing.T) { +func TestControllers(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Controller Suite") } var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + ctx, cancel = context.WithCancel(context.TODO()) + + var err error + err = logicv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + By("bootstrapping test environment") testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } - var err error + // Retrieve the first found binary directory to allow running tests from IDEs + if getFirstFoundEnvTestBinaryDir() != "" { + testEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir() + } + // cfg is defined in this file globally. cfg, err = testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = apiv08.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - - //+kubebuilder:scaffold:Scheme - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) - }) var _ = AfterSuite(func() { By("tearing down the test environment") + cancel() err := testEnv.Stop() Expect(err).NotTo(HaveOccurred()) }) + +// getFirstFoundEnvTestBinaryDir locates the first binary in the specified path. +// ENVTEST-based tests depend on specific binaries, usually located in paths set by +// controller-runtime. When running tests directly (e.g., via an IDE) without using +// Makefile targets, the 'BinaryAssetsDirectory' must be explicitly configured. +// +// This function streamlines the process by finding the required binaries, similar to +// setting the 'KUBEBUILDER_ASSETS' environment variable. To ensure the binaries are +// properly set up, run 'make setup-envtest' beforehand. +func getFirstFoundEnvTestBinaryDir() string { + basePath := filepath.Join("..", "..", "bin", "k8s") + entries, err := os.ReadDir(basePath) + if err != nil { + logf.Log.Error(err, "Failed to read directory", "path", basePath) + return "" + } + for _, entry := range entries { + if entry.IsDir() { + return filepath.Join(basePath, entry.Name()) + } + } + return "" +} diff --git a/internal/controller/workflowdef/configmap.go b/internal/controller/workflowdef/configmap.go deleted file mode 100644 index 46cc4744..00000000 --- a/internal/controller/workflowdef/configmap.go +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "context" - "path" - - "github.com/kubesmarts/logic-operator/workflowproj" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/utils/kubernetes" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const KogitoWorkflowJSONFileExt = ".sw.json" - -// CreateNewConfigMap creates a new configMap object instance with the workflow definition based on the given SonataFlow custom resource. -// It does not persist the CM into the Kubernetes storage. -// The name and namespace are the same of the given CR. -func CreateNewConfigMap(workflow *operatorapi.SonataFlow) (*corev1.ConfigMap, error) { - workflowDef, err := GetJSONWorkflow(workflow, context.TODO()) - if err != nil { - return nil, err - } - return &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: workflowproj.GetMergedLabels(workflow), - }, - Data: map[string]string{GetWorkflowDefFileName(workflow): string(workflowDef)}, - }, nil -} - -// GetWorkflowDefFileName returns the default workflow file definition that should be injected/mounted to a workflow application given a SonataFlow CR. -func GetWorkflowDefFileName(workflow *operatorapi.SonataFlow) string { - return workflow.Name + KogitoWorkflowJSONFileExt -} - -// FetchExternalResourcesConfigMapsRef fetches the Resource ConfigMaps into a LocalObjectReference that a client can mount to the workflow application. -// The map format is map[]. For example map["resource-openapi"]{MyOpenApisConfigMap} -func FetchExternalResourcesConfigMapsRef(client client.Client, workflow *operatorapi.SonataFlow) ([]operatorapi.ConfigMapWorkflowResource, error) { - var externalConfigMaps []operatorapi.ConfigMapWorkflowResource - for _, res := range workflow.Spec.Resources.ConfigMaps { - // check if there's a valid reference of the given CM - _, err := fetchConfigMapReference(client, res.ConfigMap.Name, workflow.Namespace) - if err != nil { - return nil, err - } else { - externalConfigMaps = append(externalConfigMaps, res) - } - } - return externalConfigMaps, nil -} - -func fetchConfigMapReference(client client.Client, configMapName, namespace string) (*corev1.LocalObjectReference, error) { - configMap := corev1.ConfigMap{} - err := client.Get(context.TODO(), types.NamespacedName{Name: configMapName, Namespace: namespace}, &configMap) - if err != nil { - return nil, err - } - return &corev1.LocalObjectReference{Name: configMap.Name}, nil -} - -// ExternalResCMsToVolumesAndMount creates volume mounts for ExtResType ConfigMaps references. -// See FetchExternalResourcesConfigMapsRef that should return the maps needed as input for this function. -// `baseMountPath` is a string with the base mount path to join with the given relative path in the configMap reference. -func ExternalResCMsToVolumesAndMount(configMaps []operatorapi.ConfigMapWorkflowResource, baseMountPath string) ([]corev1.Volume, []corev1.VolumeMount) { - volumes := make([]corev1.Volume, 0) - volumeMounts := make([]corev1.VolumeMount, 0) - for _, cm := range configMaps { - volumes = append(volumes, kubernetes.VolumeConfigMap(cm.ConfigMap.Name, cm.ConfigMap.Name)) - volumeMounts = append(volumeMounts, kubernetes.VolumeMount(cm.ConfigMap.Name, true, path.Join(baseMountPath, cm.WorkflowPath))) - } - return volumes, volumeMounts -} diff --git a/internal/controller/workflowdef/events.go b/internal/controller/workflowdef/events.go deleted file mode 100644 index e4aa3e98..00000000 --- a/internal/controller/workflowdef/events.go +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "github.com/kubesmarts/logic-operator/api/metadata" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - cloudevents "github.com/cloudevents/sdk-go/v2" -) - -const SonataFlowOperatorSource = "sonataflow.org/operator" - -func NewWorkflowDefinitionAvailabilityEvent(workflow *operatorapi.SonataFlow, eventSource string, serviceUrl string, available bool) *cloudevents.Event { - var status = "unavailable" - if available { - status = "available" - } - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetType("ProcessDefinitionEvent") - event.SetSource(eventSource) - event.SetExtension("kogitoprocid", workflow.Name) - event.SetExtension("partitionkey", workflow.Name) - data := make(map[string]interface{}) - data["id"] = workflow.Name - if name, ok := workflow.ObjectMeta.Annotations[metadata.Name]; ok { - data["name"] = name - } - version := workflow.ObjectMeta.Annotations[metadata.Version] - data["version"] = version - data["type"] = "SW" - data["endpoint"] = serviceUrl - data["metadata"] = map[string]interface{}{ - "status": status, - } - data["nodes"] = [0]string{} - _ = event.SetData(cloudevents.ApplicationJSON, data) - return &event -} diff --git a/internal/controller/workflowdef/image.go b/internal/controller/workflowdef/image.go deleted file mode 100644 index 83df310d..00000000 --- a/internal/controller/workflowdef/image.go +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "fmt" - - "github.com/kubesmarts/logic-operator/api/version" - - "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/internal/controller/cfg" - "github.com/kubesmarts/logic-operator/utils" -) - -const ( - defaultWorkflowDevModeImage = "docker.io/apache/incubator-kie-sonataflow-devmode" - defaultWorkflowBuilderImage = "docker.io/apache/incubator-kie-sonataflow-builder" -) - -// GetWorkflowAppImageNameTag returns the image name with tag to use for the image to be produced for a given workflow. -// Before, we generated the tags based on the workflow version annotation, however this produced the following undesired -// effects. Empirically, it was detected that, if we deploy a workflow several times, for instance, the workflow is deleted -// for a modification, and then deployed again. When the build cycle is produced, etc., if the workflow version -// remains the same, e.g. 1.0.0, the bits for the new image are not written in the respective registry (because an image -// with the given tag already exists), and thus, when the workflow executes the old bits are executed. -// To avoid this, the workflow version must be changed, for example to 2.0.0, and thus the subsequent image will have -// a different tag, and the expected bits will be stored at the registry and finally executed. -// This workflow version bump must be produced by the users, but we don't have control over this. -// So by now, considering that the operator images build is oriented to "dev" and "preview" scenarios, and -// not for "production" scenarios, we decided to use "latest" as the tag. In that way, we ensure that the last image -// produced bits will be used to execute a given workflow. -func GetWorkflowAppImageNameTag(w *v1alpha08.SonataFlow) string { - return w.Name + ":" + utils.LatestImageTag -} - -func GetDefaultWorkflowDevModeImageTag() string { - if len(cfg.GetCfg().SonataFlowDevModeImageTag) > 0 { - return cfg.GetCfg().SonataFlowDevModeImageTag - } - return GetDefaultImageTag(defaultWorkflowDevModeImage) -} - -func GetDefaultWorkflowBuilderImageTag() string { - if len(cfg.GetCfg().SonataFlowBaseBuilderImageTag) > 0 { - return cfg.GetCfg().SonataFlowBaseBuilderImageTag - } - return GetDefaultImageTag(defaultWorkflowBuilderImage) -} - -func GetDefaultImageTag(imgTag string) string { - return fmt.Sprintf("%s:%s", imgTag, version.GetImageTagVersion()) -} diff --git a/internal/controller/workflowdef/json.go b/internal/controller/workflowdef/json.go deleted file mode 100644 index 39b57205..00000000 --- a/internal/controller/workflowdef/json.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "context" - "encoding/json" - - "github.com/kubesmarts/logic-operator/log" - - "k8s.io/klog/v2" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -// GetJSONWorkflow return a Kogito compliant JSON format workflow as bytearray give a specific workflow CR -func GetJSONWorkflow(workflowCR *operatorapi.SonataFlow, ctx context.Context) ([]byte, error) { - // apply workflow metadata - workflow, err := operatorapi.ToCNCFWorkflow(workflowCR, ctx) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed converting SonataFlow into Workflow") - return nil, err - } - jsonWorkflow, err := json.Marshal(workflow) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed converting SonataFlow into JSON") - return nil, err - } - return jsonWorkflow, nil -} diff --git a/internal/controller/workflowdef/json_test.go b/internal/controller/workflowdef/json_test.go deleted file mode 100644 index 1752c40e..00000000 --- a/internal/controller/workflowdef/json_test.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "context" - "testing" - - "github.com/serverlessworkflow/sdk-go/v2/model" - "github.com/stretchr/testify/assert" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "github.com/kubesmarts/logic-operator/test" -) - -func TestSonataFlowConverter(t *testing.T) { - t.Run("verify that when SonataFlow CR is nil an error is returned", func(t *testing.T) { - // Create a SonataFlow object with metadata and spec. - ksw := test.GetBaseSonataFlow(t.Name()) - out, err := operatorapi.ToCNCFWorkflow(ksw, context.TODO()) - assert.NoError(t, err) - assert.True(t, out != nil) - assert.Equal(t, "greeting", out.ID) - //assert.Equal(t, "greeting-key", out.Key) - assert.Equal(t, "0.0.1", out.Version) - assert.Equal(t, "0.8", out.SpecVersion) - assert.Equal(t, "Greeting example on k8s!", out.Description) - assert.Equal(t, model.JqExpressionLang, out.ExpressionLang) - assert.True(t, out.Functions != nil && len(out.Functions) == 1) - assert.True(t, out.States != nil && len(out.States) == 4) - }) - -} diff --git a/internal/controller/workflowdef/services.go b/internal/controller/workflowdef/services.go deleted file mode 100644 index a8a4756d..00000000 --- a/internal/controller/workflowdef/services.go +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func ContainsEventKind(workflow *operatorapi.SonataFlow, eventKind cncfmodel.EventKind) bool { - for _, event := range workflow.Spec.Flow.Events { - if event.Kind == eventKind { - return true - } - } - return false -} diff --git a/internal/controller/workflowdef/utils.go b/internal/controller/workflowdef/utils.go deleted file mode 100644 index edbd3902..00000000 --- a/internal/controller/workflowdef/utils.go +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "github.com/serverlessworkflow/sdk-go/v2/model" - "k8s.io/apimachinery/pkg/labels" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -// HasTimeouts returns true if current workflow has configured any of the SonataFlow supported timeouts, false -// in any other case. This method might be reviewed when more timeouts are supported. -func HasTimeouts(workflow *operatorapi.SonataFlow) bool { - flow := &workflow.Spec.Flow - hasTimeouts := HasWorkflowExecTimeout(flow) || HasWorkflowEventTimeout(flow) - for i := 0; !hasTimeouts && i < len(flow.States); i++ { - state := flow.States[i] - switch state.Type { - case model.StateTypeEvent: - hasTimeouts = HasEventStateTimeouts(state.EventState) - case model.StateTypeOperation: - hasTimeouts = HasOperationStateTimeouts(state.OperationState) - case model.StateTypeSwitch: - hasTimeouts = HasSwitchStateTimeouts(state.SwitchState) - case model.StateTypeSleep: - hasTimeouts = true - case model.StateTypeParallel: - hasTimeouts = HasParallelStateTimeouts(state.ParallelState) - case model.StateTypeForEach: - hasTimeouts = HasForEachStateTimeouts(state.ForEachState) - case model.StateTypeCallback: - hasTimeouts = HasCallbackStateTimeouts(state.CallbackState) - } - } - return hasTimeouts -} - -func HasWorkflowEventTimeout(flow *operatorapi.Flow) bool { - return flow.Timeouts != nil && len(flow.Timeouts.EventTimeout) > 0 -} -func HasWorkflowExecTimeout(flow *operatorapi.Flow) bool { - return flow.Timeouts != nil && flow.Timeouts.WorkflowExecTimeout != nil && len(flow.Timeouts.WorkflowExecTimeout.Duration) > 0 -} - -func HasEventStateTimeouts(state *model.EventState) bool { - if state.Timeouts != nil && len(state.Timeouts.EventTimeout) > 0 { - return true - } - for _, onEvent := range state.OnEvents { - if hasActionsWithSleep(&onEvent.Actions) { - return true - } - } - return false -} - -func HasOperationStateTimeouts(state *model.OperationState) bool { - return hasActionsWithSleep(&state.Actions) -} - -func HasSwitchStateTimeouts(state *model.SwitchState) bool { - return state.Timeouts != nil && len(state.Timeouts.EventTimeout) > 0 -} - -func HasParallelStateTimeouts(state *model.ParallelState) bool { - for _, branch := range state.Branches { - if hasBranchTimeouts(&branch) { - return true - } - } - return false -} - -func hasBranchTimeouts(branch *model.Branch) bool { - return hasActionsWithSleep(&branch.Actions) -} - -func HasForEachStateTimeouts(state *model.ForEachState) bool { - return hasActionsWithSleep(&state.Actions) -} - -func HasCallbackStateTimeouts(state *model.CallbackState) bool { - return (state.Timeouts != nil && len(state.Timeouts.EventTimeout) > 0) || hasAnySleep(&state.Action) -} - -func hasActionsWithSleep(actions *[]model.Action) bool { - for _, action := range *actions { - if hasAnySleep(&action) { - return true - } - } - return false -} - -func hasAnySleep(action *model.Action) bool { - return action.Sleep != nil && (len(action.Sleep.Before) > 0 || len(action.Sleep.After) > 0) -} - -func HasReplicas(workflow *operatorapi.SonataFlow) bool { - return workflow.Spec.PodTemplate.Replicas != nil -} - -func HasScaleSelector(workflow *operatorapi.SonataFlow) bool { - return len(workflow.Status.Selector) > 0 -} - -func GenerateScaleSelector(workflow *operatorapi.SonataFlow) string { - labelSet := labels.Set(workflowproj.GetSelectorLabels(workflow)) - return labelSet.AsSelector().String() -} - -// IsScaledToZero returns true if the workflow has been explicitly scaled to zero, i.e., by setting -// the spec.podTemplate.replicas == 0. False in any other case, including when spec.podTemplate.replicas == nil. -func IsScaledToZero(workflow *operatorapi.SonataFlow) bool { - return workflow.Spec.PodTemplate.Replicas != nil && *workflow.Spec.PodTemplate.Replicas == int32(0) -} - -// ReplicasIsGreaterThan returns true if the workflow configured Spec.PodTemplate.Replicas is != nil, and greater -// than the given value. False in any other case. -func ReplicasIsGreaterThan(workflow *operatorapi.SonataFlow, value int32) bool { - return workflow.Spec.PodTemplate.Replicas != nil && *workflow.Spec.PodTemplate.Replicas > value -} diff --git a/internal/controller/workflowdef/utils_suite_test.go b/internal/controller/workflowdef/utils_suite_test.go deleted file mode 100644 index aa3919a7..00000000 --- a/internal/controller/workflowdef/utils_suite_test.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestProperties(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Utils Suite") -} diff --git a/internal/controller/workflowdef/utils_test.go b/internal/controller/workflowdef/utils_test.go deleted file mode 100644 index e38a6402..00000000 --- a/internal/controller/workflowdef/utils_test.go +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowdef - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -var ( - emptyDuration = "" - isoDuration = "PT30S" -) - -var _ = DescribeTable("Workflow has timeouts", - func(workflow *operatorapi.SonataFlow, expectedHasTimeouts bool) { - hasTimeouts := HasTimeouts(workflow) - Expect(hasTimeouts).Should(Equal(expectedHasTimeouts)) - }, - Entry("for a workflow with WorkflowExecTimeout", workflowWithWorkflowExecTimeout(&isoDuration), true), - Entry("for a workflow with empty WorkflowExecTimeout", workflowWithWorkflowExecTimeout(&emptyDuration), false), - Entry("for a workflow with nil WorkflowExecTimeout", workflowWithWorkflowExecTimeout(&emptyDuration), false), - - Entry("for a workflow with WorkflowEventTimeout", workflowWithWorkflowEventStateTimeout(&isoDuration), true), - Entry("for a workflow with empty WorkflowEventTimeout", workflowWithWorkflowEventStateTimeout(&emptyDuration), false), - Entry("for a workflow with nil WorkflowEventTimeout", workflowWithWorkflowEventStateTimeout(nil), false), - - Entry("for a workflow with EventState with timeouts", workflowWithEventStateWithTimeout(&isoDuration), true), - Entry("for a workflow with EventState empty timeouts", workflowWithEventStateWithTimeout(&emptyDuration), false), - Entry("for a workflow with EventState nil timeouts", workflowWithEventStateWithTimeout(&emptyDuration), false), - Entry("for a workflow with EventState with action sleep at before", workflowWithEventStateWithActionSleep(true, false), true), - Entry("for a workflow with EventState with action sleep at before", workflowWithEventStateWithActionSleep(false, true), true), - - Entry("for a workflow with OperationState with action sleep at before", workflowWithEventStateWithActionSleep(true, false), true), - Entry("for a workflow with OperationState with with action sleep at after", workflowWithEventStateWithActionSleep(false, true), true), - Entry("for a workflow with OperationState with no action sleep", workflowWithEventStateWithActionSleep(false, false), false), - - Entry("for a workflow with SwitchState with timeouts", workflowWithSwitchStateWithTimeout(&isoDuration), true), - Entry("for a workflow with SwitchState with empty timeouts", workflowWithSwitchStateWithTimeout(&emptyDuration), false), - Entry("for a workflow with SwitchState with nil timeouts", workflowWithSwitchStateWithTimeout(nil), false), - - Entry("for a workflow with SleepState", workflowWithSleepState(), true), - - Entry("for a workflow with ParallelState with branch with sleep at before", workflowWithParallelState(true, false), true), - Entry("for a workflow with ParallelState with branch with sleep at after", workflowWithParallelState(false, true), true), - Entry("for a workflow with ParallelState with branches with sleep at before and after", workflowWithParallelState(true, true), true), - Entry("for a workflow with ParallelState with no sleep branches", workflowWithParallelState(false, false), false), - - Entry("for a workflow with ForEachState with action sleep at before", workflowWithForEachStateWithActionSleep(true, false), true), - Entry("for a workflow with ForEachState with with action sleep at after", workflowWithForEachStateWithActionSleep(false, true), true), - Entry("for a workflow with ForEachState with no action sleep", workflowWithForEachStateWithActionSleep(false, false), false), - - Entry("for a workflow with CallbackState with timeouts", workflowWithCallbackStateTimeoutAndActionSleep(&isoDuration, nil, nil), true), - Entry("for a workflow with CallbackState with nil timeouts and before action sleep", workflowWithCallbackStateTimeoutAndActionSleep(nil, &isoDuration, nil), true), - Entry("for a workflow with CallbackState with nil timeouts and after action sleep", workflowWithCallbackStateTimeoutAndActionSleep(nil, nil, &isoDuration), true), - Entry("for a workflow with CallbackState with nil timeouts and no action sleep", workflowWithCallbackStateTimeoutAndActionSleep(nil, nil, nil), false), -) - -func workflowWithWorkflowExecTimeout(duration *string) *operatorapi.SonataFlow { - wf := generateWorkflow() - if duration != nil { - wf.Spec.Flow.Timeouts = &cncfmodel.Timeouts{} - wf.Spec.Flow.Timeouts.WorkflowExecTimeout = &cncfmodel.WorkflowExecTimeout{ - Duration: *duration, - } - } - return wf -} - -func workflowWithWorkflowEventStateTimeout(duration *string) *operatorapi.SonataFlow { - wf := generateWorkflow() - if duration != nil { - wf.Spec.Flow.Timeouts = &cncfmodel.Timeouts{ - EventTimeout: *duration, - } - } - return wf -} - -func workflowWithEventStateWithTimeout(duration *string) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateEventState() - if duration != nil { - state.EventState.Timeouts = &cncfmodel.EventStateTimeout{EventTimeout: *duration} - } - wf.Spec.Flow.States = []cncfmodel.State{*state} - return wf -} - -func workflowWithEventStateWithActionSleep(before bool, after bool) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateEventState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - state.EventState.OnEvents = []cncfmodel.OnEvents{ - { - Actions: generateActionsWithSleep(before, after), - }, - } - return wf -} - -func workflowWithOperationStateWithActionSleep(before bool, after bool) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateOperationState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - state.OperationState.Actions = generateActionsWithSleep(before, after) - return wf -} - -func workflowWithSwitchStateWithTimeout(duration *string) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateSwitchState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - if duration != nil { - state.SwitchState.Timeouts = &cncfmodel.SwitchStateTimeout{ - EventTimeout: *duration, - } - } - return wf -} - -func workflowWithSleepState() *operatorapi.SonataFlow { - wf := generateWorkflow() - wf.Spec.Flow.States = []cncfmodel.State{*generateSleepState()} - return wf -} - -func workflowWithParallelState(branchWithBeforeSleep bool, branchWithAfterSleep bool) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateParallelState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - if branchWithBeforeSleep { - branch := cncfmodel.Branch{ - Actions: []cncfmodel.Action{{Sleep: &cncfmodel.Sleep{Before: "PT5S"}}}, - } - state.ParallelState.Branches = append(state.ParallelState.Branches, branch) - } - if branchWithAfterSleep { - branch := cncfmodel.Branch{ - Actions: []cncfmodel.Action{{Sleep: &cncfmodel.Sleep{After: "PT5S"}}}, - } - state.ParallelState.Branches = append(state.ParallelState.Branches, branch) - } - return wf -} - -func workflowWithForEachStateWithActionSleep(before bool, after bool) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateForEachState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - state.ForEachState.Actions = generateActionsWithSleep(before, after) - return wf -} - -func workflowWithCallbackStateTimeoutAndActionSleep(duration *string, before *string, after *string) *operatorapi.SonataFlow { - wf := generateWorkflow() - state := generateCallbackState() - wf.Spec.Flow.States = []cncfmodel.State{*state} - if duration != nil { - state.CallbackState.Timeouts = &cncfmodel.CallbackStateTimeout{EventTimeout: *duration} - } - state.CallbackState.Action = cncfmodel.Action{} - if before != nil || after != nil { - state.CallbackState.Action.Sleep = &cncfmodel.Sleep{} - if before != nil { - state.CallbackState.Action.Sleep.Before = *before - } - if after != nil { - state.CallbackState.Action.Sleep.After = *after - } - } - return wf -} - -func generateWorkflow() *operatorapi.SonataFlow { - wf := &operatorapi.SonataFlow{ - Spec: operatorapi.SonataFlowSpec{ - Flow: operatorapi.Flow{}, - }, - } - return wf -} - -func generateEventState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeEvent, - }, - EventState: &cncfmodel.EventState{}, - } -} - -func generateOperationState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeOperation, - }, - OperationState: &cncfmodel.OperationState{}, - } -} - -func generateSwitchState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeSwitch, - }, - SwitchState: &cncfmodel.SwitchState{}, - } -} - -func generateSleepState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeSleep, - }, - SleepState: &cncfmodel.SleepState{}, - } -} - -func generateParallelState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeParallel, - }, - ParallelState: &cncfmodel.ParallelState{ - Branches: []cncfmodel.Branch{}, - }, - } -} - -func generateForEachState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeForEach, - }, - ForEachState: &cncfmodel.ForEachState{}, - } -} - -func generateCallbackState() *cncfmodel.State { - return &cncfmodel.State{ - BaseState: cncfmodel.BaseState{ - Type: cncfmodel.StateTypeCallback, - }, - CallbackState: &cncfmodel.CallbackState{}, - } -} - -func generateActionsWithSleep(before bool, after bool) []cncfmodel.Action { - var actions []cncfmodel.Action - if before { - actions = append(actions, cncfmodel.Action{ - Sleep: &cncfmodel.Sleep{ - Before: "PT30S", - }, - }) - } - if after { - actions = append(actions, cncfmodel.Action{ - Sleep: &cncfmodel.Sleep{ - After: "PT30S", - }, - }) - } - return actions -} diff --git a/internal/controller/workflows/workflows.go b/internal/controller/workflows/workflows.go deleted file mode 100644 index 9800c459..00000000 --- a/internal/controller/workflows/workflows.go +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 workflows - -import ( - "context" - - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -var _ WorkflowManager = &workflowManager{} - -// WorkflowManager offers a management interface for operations with SonataFlows instances outside the controller's package. -// Meant to be used by other packages that don't have access to a SonataFlow instance coming from a reconciliation cycle. -type WorkflowManager interface { - SetBuiltStatusToRunning(message string) error - GetWorkflow() *v1alpha08.SonataFlow -} - -type workflowManager struct { - workflow *v1alpha08.SonataFlow - client client.Client - ctx context.Context -} - -func (w *workflowManager) GetWorkflow() *v1alpha08.SonataFlow { - return w.workflow -} - -func (w *workflowManager) SetBuiltStatusToRunning(message string) error { - w.workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildIsRunningReason, message) - return w.client.Status().Update(w.ctx, w.workflow) -} - -func NewManager(client client.Client, ctx context.Context, ns, name string) (WorkflowManager, error) { - workflow := &v1alpha08.SonataFlow{} - if err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: ns}, workflow); err != nil { - return nil, err - } - return &workflowManager{ - workflow: workflow, - client: client, - ctx: ctx, - }, nil -} diff --git a/internal/manager/worker.go b/internal/manager/worker.go deleted file mode 100644 index 3d4514a0..00000000 --- a/internal/manager/worker.go +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 manager - -import ( - "time" -) - -const ( - SonataFlowControllerWorkerSize = 100 -) - -var ( - sonataFlowControllerWorker *Worker - operatorStarTime time.Time -) - -type Runnable func() - -type Worker struct { - ch chan Runnable -} - -func SetOperatorStartTime() { - operatorStarTime = time.Now() -} - -func GetOperatorStartTime() time.Time { - return operatorStarTime -} - -func GetSFCWorker() *Worker { - return sonataFlowControllerWorker -} - -func InitializeSFCWorker(size int) *Worker { - worker := NewWorker(size) - worker.Start() - sonataFlowControllerWorker = &worker - return sonataFlowControllerWorker -} - -func NewWorker(size int) Worker { - return Worker{ch: make(chan Runnable, size)} -} - -func (w Worker) Start() { - go func(ch chan Runnable) { - for { - r, ok := <-ch - if !ok { - break - } else { - r() - } - } - }(w.ch) -} - -func (w Worker) RunAsync(r Runnable) { - w.ch <- r -} diff --git a/operator.yaml b/operator.yaml deleted file mode 100644 index a2d2dfbb..00000000 --- a/operator.yaml +++ /dev/null @@ -1,28523 +0,0 @@ -# Copyright 2026 The Kubesmarts 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. - -apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-system ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflowbuilds.sonataflow.org -spec: - group: sonataflow.org - names: - kind: SonataFlowBuild - listKind: SonataFlowBuildList - plural: sonataflowbuilds - shortNames: - - sfb - - sfbuild - - sfbuilds - singular: sonataflowbuild - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.imageTag - name: Image - type: string - - jsonPath: .status.buildPhase - name: Phase - type: string - name: v1alpha08 - schema: - openAPIV3Schema: - description: SonataFlowBuild is an internal custom resource to control workflow - build instances in the target platform - 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: SonataFlowBuildSpec define the desired state of th SonataFlowBuild. - properties: - arguments: - description: |- - Arguments lists the command line arguments to send to the internal builder command. - Depending on the build method you might set this attribute instead of BuildArgs. - For example: ".spec.arguments=verbose=3". - Please see the SonataFlow guides. - items: - type: string - type: array - buildArgs: - description: Optional build arguments that can be set to the internal - build (e.g. Docker ARG) - items: - description: EnvVar represents an environment variable present in - a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envs: - description: Optional environment variables to add to the internal - build - items: - description: EnvVar represents an environment variable present in - a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - resources: - description: Resources optional compute resource requirements for - the builder - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - timeout: - description: |- - Timeout defines the Build maximum execution duration. - The Build deadline is set to the Build start time plus the Timeout duration. - If the Build deadline is exceeded, the Build context is canceled, - and its phase set to BuildPhaseFailed. - format: duration - type: string - type: object - status: - description: SonataFlowBuildStatus defines the observed state of SonataFlowBuild - properties: - buildPhase: - description: BuildPhase Current phase of the build - type: string - error: - description: Error Last error found during build - type: string - imageTag: - description: ImageTag The final image tag produced by this build instance - type: string - innerBuild: - description: InnerBuild is a reference to an internal build object, - which can be anything known only to internal builders. - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflowclusterplatforms.sonataflow.org -spec: - group: sonataflow.org - names: - kind: SonataFlowClusterPlatform - listKind: SonataFlowClusterPlatformList - plural: sonataflowclusterplatforms - singular: sonataflowclusterplatform - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.platformRef.name - name: Platform_Name - type: string - - jsonPath: .spec.platformRef.namespace - name: Platform_NS - type: string - - jsonPath: .status.conditions[?(@.type=='Succeed')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Succeed')].reason - name: Reason - type: string - name: v1alpha08 - schema: - openAPIV3Schema: - description: SonataFlowClusterPlatform is the Schema for the sonataflowclusterplatforms - API - 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: SonataFlowClusterPlatformSpec defines the desired state of - SonataFlowClusterPlatform - properties: - capabilities: - description: Capabilities defines which platform capabilities should - be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]` - properties: - workflows: - description: Workflows defines which platform capabilities should - be applied to workflows cluster-wide. - items: - enum: - - services - type: string - type: array - type: object - platformRef: - description: PlatformRef defines which existing SonataFlowPlatform's - supporting services should be used cluster-wide. - properties: - name: - description: Name of the SonataFlowPlatform - type: string - namespace: - description: Namespace of the SonataFlowPlatform - type: string - required: - - name - - namespace - type: object - required: - - platformRef - type: object - status: - description: SonataFlowClusterPlatformStatus defines the observed state - of SonataFlowClusterPlatform - properties: - conditions: - description: The latest available observations of a resource's current - state. - items: - description: Condition describes the common structure for conditions - in our types - properties: - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human-readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type condition for the given object - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: The generation observed by the deployment controller. - format: int64 - type: integer - version: - description: Version the operator version controlling this ClusterPlatform - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflowplatforms.sonataflow.org -spec: - group: sonataflow.org - names: - kind: SonataFlowPlatform - listKind: SonataFlowPlatformList - plural: sonataflowplatforms - shortNames: - - sfp - - sfplatform - - sfplatforms - singular: sonataflowplatform - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.cluster - name: Cluster - type: string - - jsonPath: .status.conditions[?(@.type=='Succeed')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Succeed')].reason - name: Reason - type: string - name: v1alpha08 - schema: - openAPIV3Schema: - description: SonataFlowPlatform is the descriptor for the workflow platform - infrastructure. - 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: SonataFlowPlatformSpec defines the desired state of SonataFlowPlatform - properties: - build: - description: Build Attributes for building workflows in the target - platform - properties: - config: - description: Describes the platform configuration for building - workflows. - properties: - baseImage: - description: |- - a base image that can be used as base layer for all images. - It can be useful if you want to provide some custom base image with further utility software - type: string - registry: - description: Registry the registry where to publish the built - image - properties: - address: - description: the URI to access - type: string - ca: - description: the configmap which stores the Certificate - Authority - type: string - insecure: - description: if the container registry is insecure (ie, - http only) - type: boolean - organization: - description: the registry organization - type: string - secret: - description: the secret where credentials are stored - type: string - type: object - strategy: - description: |- - BuildStrategy to use to build workflows in the platform. - Usually, the operator elect the strategy based on the platform. - Note that this field might be read only in certain scenarios. - type: string - strategyOptions: - additionalProperties: - type: string - description: |- - BuildStrategyOptions additional options to add to the build strategy. - See https://sonataflow.org/serverlessworkflow/main/cloud/operator/build-and-deploy-workflows.html - type: object - timeout: - description: how much time to wait before time out the build - process - type: string - type: object - template: - description: Describes a build template for building workflows. - Base for the internal SonataFlowBuild resource. - properties: - arguments: - description: |- - Arguments lists the command line arguments to send to the internal builder command. - Depending on the build method you might set this attribute instead of BuildArgs. - For example: ".spec.arguments=verbose=3". - Please see the SonataFlow guides. - items: - type: string - type: array - buildArgs: - description: Optional build arguments that can be set to the - internal build (e.g. Docker ARG) - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envs: - description: Optional environment variables to add to the - internal build - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - resources: - description: Resources optional compute resource requirements - for the builder - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - timeout: - description: |- - Timeout defines the Build maximum execution duration. - The Build deadline is set to the Build start time plus the Timeout duration. - If the Build deadline is exceeded, the Build context is canceled, - and its phase set to BuildPhaseFailed. - format: duration - type: string - type: object - type: object - devMode: - description: DevMode Attributes for running workflows in devmode (immutable, - no build required) - properties: - baseImage: - description: Base image to run the Workflow in dev mode instead - of the operator's default. - type: string - type: object - eventing: - description: Eventing describes the information required for Knative - Eventing integration in the platform. - properties: - broker: - description: Broker to communicate with workflow deployment. It - can be the default broker when the workflow, Dataindex, or Jobservice - does not have a sink or source specified. - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme and - non-empty host) pointing to the target or a relative URI. - Relative URIs will be resolved using the base URI retrieved - from Ref. - type: string - type: object - type: object - monitoring: - description: Settings for Prometheus monitoring - properties: - enabled: - description: Enabled indicates whether monitoring with Prometheus - metrics is enabled - type: boolean - type: object - persistence: - description: |- - Persistence defines the platform persistence configuration. When this field is set, - the configuration is used as the persistence for platform services and SonataFlow instances - that don't provide one of their own. - maxProperties: 1 - properties: - postgresql: - description: Connect configured services to a postgresql database. - maxProperties: 2 - minProperties: 2 - properties: - jdbcUrl: - description: |- - PostgreSql JDBC URL. Mutually exclusive to serviceRef. - e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - type: string - secretRef: - description: Secret reference to the database user credentials - properties: - name: - description: Name of the postgresql credentials secret. - type: string - passwordKey: - description: Defaults to POSTGRESQL_PASSWORD - type: string - userKey: - description: Defaults to POSTGRESQL_USER - type: string - required: - - name - type: object - serviceRef: - description: Service reference to postgresql datasource. Mutually - exclusive to jdbcUrl. - properties: - databaseName: - description: Name of postgresql database to be used. Defaults - to "sonataflow" - type: string - name: - description: Name of the postgresql k8s service. - type: string - namespace: - description: Namespace of the postgresql k8s service. - Defaults to the SonataFlowPlatform's local namespace. - type: string - port: - description: Port to use when connecting to the postgresql - k8s service. Defaults to 5432. - type: integer - required: - - name - type: object - required: - - secretRef - type: object - type: object - properties: - description: |- - Properties defines the property set for a given actor in the current context. - For example, the workflow managed properties. One can define here a set of properties for SonataFlow deployments - that will be reused across every workflow deployment. - - These properties MAY NOT be propagated to a SonataFlowClusterPlatform since PropertyVarSource can only refer local context sources. - properties: - flow: - description: Properties that will be added to the SonataFlow managed - configMaps in the current context. - items: - description: |- - PropertyVar is the entry for a property set derived from the Kubernetes API EnvVar. - Note that the name doesn't have to match C_IDENTIFIER. - properties: - name: - description: The property name - type: string - value: - description: Defaults to "". - type: string - valueFrom: - description: Source for the property's value. Cannot be - used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the flow's - namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - type: object - services: - description: |- - Services attributes for deploying supporting applications like Data Index & Job Service. - Only workflows without the `sonataflow.org/profile: dev` annotation will be configured to use these service(s). - Setting this will override the use of any cluster-scoped services that might be defined via `SonataFlowClusterPlatform`. - properties: - dataIndex: - description: 'Deploys the Data Index service for use by workflows - without the `sonataflow.org/profile: dev` annotation.' - properties: - enabled: - description: 'Determines whether workflows without the `sonataflow.org/profile: - dev` annotation should be configured to use this service' - type: boolean - persistence: - description: Persists service to a datasource of choice. Ephemeral - by default. - maxProperties: 2 - properties: - dbMigrationStrategy: - default: service - description: |- - DB Migration approach for data-index and jobs-service. Use the following values as described. - job: use job based approach provided by the SonataFlow operator. - service: service itself shall migrate the db and will not use SonataFlow operator. - none: no database migration functionality needed. - type: string - postgresql: - description: Connect configured services to a postgresql - database. - maxProperties: 2 - minProperties: 2 - properties: - jdbcUrl: - description: |- - PostgreSql JDBC URL. Mutually exclusive to serviceRef. - e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - type: string - secretRef: - description: Secret reference to the database user - credentials - properties: - name: - description: Name of the postgresql credentials - secret. - type: string - passwordKey: - description: Defaults to POSTGRESQL_PASSWORD - type: string - userKey: - description: Defaults to POSTGRESQL_USER - type: string - required: - - name - type: object - serviceRef: - description: Service reference to postgresql datasource. - Mutually exclusive to jdbcUrl. - properties: - databaseName: - description: Name of postgresql database to be - used. Defaults to "sonataflow" - type: string - databaseSchema: - description: Schema of postgresql database to - be used. Defaults to "data-index-service" - type: string - name: - description: Name of the postgresql k8s service. - type: string - namespace: - description: Namespace of the postgresql k8s service. - Defaults to the SonataFlowPlatform's local namespace. - type: string - port: - description: Port to use when connecting to the - postgresql k8s service. Defaults to 5432. - type: integer - required: - - name - type: object - required: - - secretRef - type: object - type: object - podTemplate: - description: PodTemplate describes the deployment details - of this platform service instance. - properties: - activeDeadlineSeconds: - description: |- - Optional duration in seconds the pod may be active on the node relative to - StartTime before the system will actively try to mark it failed and kill associated containers. - Value must be a positive integer. - format: int64 - type: integer - affinity: - description: If specified, the pod's scheduling constraints - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - automountServiceAccountToken: - description: AutomountServiceAccountToken indicates whether - a service account token should be automatically mounted. - type: boolean - container: - description: |- - Container is the Kubernetes container where the application should run. - One can change this attribute in order to override the defaults provided by the operator. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before being - terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before being - terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - type: object - containers: - description: |- - List of containers belonging to the pod. - Containers cannot currently be added or removed. - There must be at least one container in a Pod. - Cannot be updated. - items: - description: A single application container that you - want to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a - C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents - resource resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block - devices to be used by the container. - items: - description: volumeDevice describes a mapping - of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside - of the container that the device will be - mapped to. - type: string - name: - description: name must match the name of a - persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting - of a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a - Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS resolver - options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - enableServiceLinks: - description: |- - EnableServiceLinks indicates whether information about services should be injected into pod's - environment variables, matching the syntax of Docker links. - Optional: Defaults to true. - type: boolean - hostAliases: - description: |- - HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. - items: - description: |- - HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the - pod's hosts file. - properties: - hostnames: - description: Hostnames for the above IP address. - items: - type: string - type: array - x-kubernetes-list-type: atomic - ip: - description: IP address of the host file entry. - type: string - required: - - ip - type: object - type: array - hostIPC: - description: |- - Use the host's ipc namespace. - Optional: Default to false. - type: boolean - hostNetwork: - description: |- - Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. - Default to false. - type: boolean - hostPID: - description: |- - Use the host's pid namespace. - Optional: Default to false. - type: boolean - hostUsers: - description: |- - Use the host's user namespace. - Optional: Default to true. - If set to true or not present, the pod will be run in the host user namespace, useful - for when the pod needs a feature only available to the host user namespace, such as - loading a kernel module with CAP_SYS_MODULE. - When set to false, a new userns is created for the pod. Setting false is useful for - mitigating container breakout vulnerabilities even allowing users to run their - containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - type: boolean - hostname: - description: |- - Specifies the hostname of the Pod - If not specified, the pod's hostname will be set to a system-defined value. - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: |- - List of initialization containers belonging to the pod. - Init containers are executed in order prior to containers being started. If any - init container fails, the pod is considered to have failed and is handled according - to its restartPolicy. The name for an init container or normal container must be - unique among all containers. - Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - The resourceRequirements of an init container are taken into account during scheduling - by finding the highest request/limit for each resource type, and then using the max of - of that value or the sum of the normal containers. Limits are applied to init containers - in a similar fashion. - Init containers cannot currently be added or removed. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - items: - description: A single application container that you - want to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a - C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents - resource resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block - devices to be used by the container. - items: - description: volumeDevice describes a mapping - of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside - of the container that the device will be - mapped to. - type: string - name: - description: name must match the name of a - persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting - of a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a - Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - nodeName: - description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - 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/ - type: object - x-kubernetes-map-type: atomic - os: - description: |- - Specifies the OS of the containers in the pod. - Some pod and container fields are restricted if this is set. - - If the OS field is set to linux, the following fields must be unset: - -securityContext.windowsOptions - - If the OS field is set to windows, following fields must be unset: - - spec.hostPID - - spec.hostIPC - - spec.hostUsers - - spec.securityContext.seLinuxOptions - - spec.securityContext.seccompProfile - - spec.securityContext.fsGroup - - spec.securityContext.fsGroupChangePolicy - - spec.securityContext.sysctls - - spec.shareProcessNamespace - - spec.securityContext.runAsUser - - spec.securityContext.runAsGroup - - spec.securityContext.supplementalGroups - - spec.containers[*].securityContext.seLinuxOptions - - spec.containers[*].securityContext.seccompProfile - - spec.containers[*].securityContext.capabilities - - spec.containers[*].securityContext.readOnlyRootFilesystem - - spec.containers[*].securityContext.privileged - - spec.containers[*].securityContext.allowPrivilegeEscalation - - spec.containers[*].securityContext.procMount - - spec.containers[*].securityContext.runAsUser - - spec.containers[*].securityContext.runAsGroup - properties: - name: - description: |- - Name is the name of the operating system. The currently supported values are linux and windows. - Additional value may be defined in future and can be one of: - https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration - Clients should expect to handle additional values and treat unrecognized values in this field as os: null - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - This field will be autopopulated at admission time by the RuntimeClass admission controller. If - the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - The RuntimeClass admission controller will reject Pod create requests which have the overhead already - set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - type: object - podDisruptionBudget: - description: |- - Defines the Kubernetes PodDisruptionBudgetSpec for this service. When configured, the SonataFlowPlatform controller - will automatically create a PodDisruptionBudget based on this specification that targets the service Deployment. - Currently only apply for the Data Index. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at most "maxUnavailable" pods selected by - "selector" are unavailable after the eviction, i.e. even in absence of - the evicted pod. For example, one can prevent all voluntary evictions - by specifying 0. This is a mutually exclusive setting with "minAvailable". - x-kubernetes-int-or-string: true - minAvailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at least "minAvailable" pods selected by - "selector" will still be available after the eviction, i.e. even in the - absence of the evicted pod. So for example you can prevent all voluntary - evictions by specifying "100%". This is a mutually exclusive setting with "maxUnavailable". - x-kubernetes-int-or-string: true - type: object - preemptionPolicy: - description: |- - PreemptionPolicy is the Policy for preempting pods with lower priority. - One of Never, PreemptLowerPriority. - Defaults to PreemptLowerPriority if unset. - type: string - priority: - description: |- - The priority value. Various system components use this field to find the - priority of the pod. When Priority Admission Controller is enabled, it - prevents users from setting this field. The admission controller populates - this field from PriorityClassName. - The higher the value, the higher the priority. - format: int32 - type: integer - priorityClassName: - description: |- - If specified, indicates the pod's priority. "system-node-critical" and - "system-cluster-critical" are two special keywords which indicate the - highest priorities with the former being the highest priority. Any other - name must be defined by creating a PriorityClass object with that name. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessGates: - description: |- - If specified, all readiness gates will be evaluated for pod readiness. - A pod is ready when all its containers are ready AND - all conditions specified in the readiness gates have status equal to "True" - More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - items: - description: PodReadinessGate contains the reference - to a pod condition - properties: - conditionType: - description: ConditionType refers to a condition - in the pod's condition list with matching type. - type: string - required: - - conditionType - type: object - type: array - replicas: - format: int32 - type: integer - resourceClaims: - description: |- - ResourceClaims defines which ResourceClaims must be allocated - and reserved before the Pod is allowed to start. The resources - will be made available to those containers which consume them - by name. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. - items: - description: |- - PodResourceClaim references exactly one ResourceClaim, either directly - or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim - for the pod. - - It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. - Containers that need access to the ResourceClaim reference it with this name. - properties: - name: - description: |- - Name uniquely identifies this resource claim inside the pod. - This must be a DNS_LABEL. - type: string - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. - - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. - - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restartPolicy: - description: |- - Restart policy for all containers within the pod. - One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - Default to Always. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - type: string - runtimeClassName: - description: |- - RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - empty definition that uses the default runtime handler. - More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - type: string - schedulerName: - description: |- - If specified, the pod will be dispatched by specified scheduler. - If not specified, the pod will be dispatched by default scheduler. - type: string - schedulingGates: - description: |- - SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - scheduler will not attempt to schedule the pod. - - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. - items: - description: PodSchedulingGate is associated to a Pod - to guard its scheduling. - properties: - name: - description: |- - Name of the scheduling gate. - Each scheduling gate must have a unique name field. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - description: |- - SecurityContext holds pod-level security attributes and common container settings. - Optional: Defaults to empty. See type description for default values of each field. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that - applies to the container. - type: string - role: - description: Role is a SELinux role label that - applies to the container. - type: string - type: - description: Type is a SELinux type label that - applies to the container. - type: string - user: - description: User is a SELinux user label that - applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the ServiceAccount to use to run this pod. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - setHostnameAsFQDN: - description: |- - If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - If a pod does not have FQDN, this has no effect. - Default to false. - type: boolean - shareProcessNamespace: - description: |- - Share a single process namespace between all of the containers in a pod. - When this is set containers will be able to view and signal processes from other containers - in the same pod, and the first process in each container will not be assigned PID 1. - HostPID and ShareProcessNamespace cannot both be set. - Optional: Default to false. - type: boolean - subdomain: - description: |- - If specified, the fully qualified Pod hostname will be "...svc.". - If not specified, the pod will not have a domainname at all. - type: string - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - If this value is nil, the default grace period will be used instead. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - Defaults to 30 seconds. - format: int64 - type: integer - tolerations: - description: If specified, the pod's tolerations. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of pods ought to spread across topology - domains. Scheduler will schedule pods in a way which abides by the constraints. - All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how - to spread matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: |- - List of volumes that can be mounted by containers belonging to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes - items: - description: Volume represents a named volume in a pod - that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data - Disk mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching - mode: None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data - disk in the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk - in the blob storage - type: string - fsType: - default: ext4 - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: - multiple blob disks per storage account Dedicated: - single blob disk per storage account Managed: - azure managed data disk (only in managed availability - set). defaults to shared' - type: string - readOnly: - default: false - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File - Service mount on the host and bind mount to the - pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret - that contains Azure Storage Account Name and - Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on - the host that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - description: 'path is Optional: Used as the - mounted root, rather than the full Ceph tree, - default is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that - should populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API - about the pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API - volume file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name, namespace and uid are supported.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. - Must not be absolute or contain the - ''..'' path. Must be utf-8 encoded. - The first item of the relative path - must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - 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 - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - 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 - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query - over volumes to consider for binding. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding - reference to the PersistentVolume - backing this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource - that is attached to a kubelet's host machine and - then exposed to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - lun: - description: 'lun is Optional: FC target lun - number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target - worldwide names (WWNs)' - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver - to use for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field - holds extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume - attached to a kubelet's host machine. This depends - on the Flocker control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the - dataset. This is unique identifier of a Flocker - dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for - the specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - image: - description: |- - image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. - The volume is resolved at pod startup depending on which PullPolicy value is provided: - - - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - - The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. - A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. - The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. - The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). - The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. - properties: - pullPolicy: - description: |- - Policy for pulling OCI objects. Possible values are: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - type: string - reference: - description: |- - Required: Image or artifact reference to be used. - Behaves in the same way as pod.spec.containers[*].image. - Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether - support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether - support iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified - Name. - type: string - iscsiInterface: - default: default - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun - number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - x-kubernetes-list-type: atomic - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for - iSCSI target and initiator authentication - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets - host machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies - Photon Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a - Portworx volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources - secrets, configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: |- - sources is the list of volume projections. Each entry in this list - handles one source. - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - name: - description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. - type: string - optional: - description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the - volume root to write the bundle. - type: string - signerName: - description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. - type: string - required: - - path - type: object - configMap: - description: configMap information about - the configMap data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key - to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether - the ConfigMap or its keys must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about - the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile - represents information to create - the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects - a field of the pod: only annotations, - labels, name, namespace and - uid are supported.' - properties: - apiVersion: - description: Version of - the schema the FieldPath - is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the - field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path - is the relative path name - of the file to be created. - Must not be absolute or contain - the ''..'' path. Must be utf-8 - encoded. The first item of - the relative path must not - start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container - name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the - output format of the exposed - resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: - resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - secret: - description: secret information about - the secret data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key - to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify - whether the Secret or its key must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to - project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - quobyte: - description: quobyte represents a Quobyte mount - on the host that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references - an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - default: /etc/ceph/keyring - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - default: rbd - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - default: admin - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent - volume attached and mounted on Kubernetes nodes. - properties: - fsType: - default: xfs - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of - the ScaleIO API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of - the ScaleIO Protection Domain for the configured - storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable - SSL communication with Gateway, default false - type: boolean - storageMode: - default: ThinProvisioned - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage - Pool associated with the protection domain. - type: string - system: - description: system is the name of the storage - system as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether - the Secret or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage - Policy Based Management (SPBM) profile ID - associated with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage - Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - source: - description: Defines the source where the Dataindex receives - events from - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address - Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme - and non-empty host) pointing to the target or a relative - URI. Relative URIs will be resolved using the base URI - retrieved from Ref. - type: string - type: object - type: object - jobService: - description: 'Deploys the Job service for use by workflows without - the `sonataflow.org/profile: dev` annotation.' - properties: - enabled: - description: 'Determines whether workflows without the `sonataflow.org/profile: - dev` annotation should be configured to use this service' - type: boolean - persistence: - description: Persists service to a datasource of choice. Ephemeral - by default. - maxProperties: 2 - properties: - dbMigrationStrategy: - default: service - description: |- - DB Migration approach for data-index and jobs-service. Use the following values as described. - job: use job based approach provided by the SonataFlow operator. - service: service itself shall migrate the db and will not use SonataFlow operator. - none: no database migration functionality needed. - type: string - postgresql: - description: Connect configured services to a postgresql - database. - maxProperties: 2 - minProperties: 2 - properties: - jdbcUrl: - description: |- - PostgreSql JDBC URL. Mutually exclusive to serviceRef. - e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - type: string - secretRef: - description: Secret reference to the database user - credentials - properties: - name: - description: Name of the postgresql credentials - secret. - type: string - passwordKey: - description: Defaults to POSTGRESQL_PASSWORD - type: string - userKey: - description: Defaults to POSTGRESQL_USER - type: string - required: - - name - type: object - serviceRef: - description: Service reference to postgresql datasource. - Mutually exclusive to jdbcUrl. - properties: - databaseName: - description: Name of postgresql database to be - used. Defaults to "sonataflow" - type: string - databaseSchema: - description: Schema of postgresql database to - be used. Defaults to "data-index-service" - type: string - name: - description: Name of the postgresql k8s service. - type: string - namespace: - description: Namespace of the postgresql k8s service. - Defaults to the SonataFlowPlatform's local namespace. - type: string - port: - description: Port to use when connecting to the - postgresql k8s service. Defaults to 5432. - type: integer - required: - - name - type: object - required: - - secretRef - type: object - type: object - podTemplate: - description: PodTemplate describes the deployment details - of this platform service instance. - properties: - activeDeadlineSeconds: - description: |- - Optional duration in seconds the pod may be active on the node relative to - StartTime before the system will actively try to mark it failed and kill associated containers. - Value must be a positive integer. - format: int64 - type: integer - affinity: - description: If specified, the pod's scheduling constraints - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - automountServiceAccountToken: - description: AutomountServiceAccountToken indicates whether - a service account token should be automatically mounted. - type: boolean - container: - description: |- - Container is the Kubernetes container where the application should run. - One can change this attribute in order to override the defaults provided by the operator. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before being - terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before being - terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - type: object - containers: - description: |- - List of containers belonging to the pod. - Containers cannot currently be added or removed. - There must be at least one container in a Pod. - Cannot be updated. - items: - description: A single application container that you - want to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a - C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents - resource resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block - devices to be used by the container. - items: - description: volumeDevice describes a mapping - of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside - of the container that the device will be - mapped to. - type: string - name: - description: name must match the name of a - persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting - of a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a - Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS resolver - options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - enableServiceLinks: - description: |- - EnableServiceLinks indicates whether information about services should be injected into pod's - environment variables, matching the syntax of Docker links. - Optional: Defaults to true. - type: boolean - hostAliases: - description: |- - HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. - items: - description: |- - HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the - pod's hosts file. - properties: - hostnames: - description: Hostnames for the above IP address. - items: - type: string - type: array - x-kubernetes-list-type: atomic - ip: - description: IP address of the host file entry. - type: string - required: - - ip - type: object - type: array - hostIPC: - description: |- - Use the host's ipc namespace. - Optional: Default to false. - type: boolean - hostNetwork: - description: |- - Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. - Default to false. - type: boolean - hostPID: - description: |- - Use the host's pid namespace. - Optional: Default to false. - type: boolean - hostUsers: - description: |- - Use the host's user namespace. - Optional: Default to true. - If set to true or not present, the pod will be run in the host user namespace, useful - for when the pod needs a feature only available to the host user namespace, such as - loading a kernel module with CAP_SYS_MODULE. - When set to false, a new userns is created for the pod. Setting false is useful for - mitigating container breakout vulnerabilities even allowing users to run their - containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - type: boolean - hostname: - description: |- - Specifies the hostname of the Pod - If not specified, the pod's hostname will be set to a system-defined value. - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: |- - List of initialization containers belonging to the pod. - Init containers are executed in order prior to containers being started. If any - init container fails, the pod is considered to have failed and is handled according - to its restartPolicy. The name for an init container or normal container must be - unique among all containers. - Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - The resourceRequirements of an init container are taken into account during scheduling - by finding the highest request/limit for each resource type, and then using the max of - of that value or the sum of the normal containers. Limits are applied to init containers - in a similar fashion. - Init containers cannot currently be added or removed. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - items: - description: A single application container that you - want to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a - C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in HTTP - probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration - that the container should sleep before - being terminated. - properties: - seconds: - description: Seconds is the number of - seconds to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to - connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents - resource resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block - devices to be used by the container. - items: - description: volumeDevice describes a mapping - of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside - of the container that the device will be - mapped to. - type: string - name: - description: name must match the name of a - persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting - of a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a - Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - nodeName: - description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - 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/ - type: object - x-kubernetes-map-type: atomic - os: - description: |- - Specifies the OS of the containers in the pod. - Some pod and container fields are restricted if this is set. - - If the OS field is set to linux, the following fields must be unset: - -securityContext.windowsOptions - - If the OS field is set to windows, following fields must be unset: - - spec.hostPID - - spec.hostIPC - - spec.hostUsers - - spec.securityContext.seLinuxOptions - - spec.securityContext.seccompProfile - - spec.securityContext.fsGroup - - spec.securityContext.fsGroupChangePolicy - - spec.securityContext.sysctls - - spec.shareProcessNamespace - - spec.securityContext.runAsUser - - spec.securityContext.runAsGroup - - spec.securityContext.supplementalGroups - - spec.containers[*].securityContext.seLinuxOptions - - spec.containers[*].securityContext.seccompProfile - - spec.containers[*].securityContext.capabilities - - spec.containers[*].securityContext.readOnlyRootFilesystem - - spec.containers[*].securityContext.privileged - - spec.containers[*].securityContext.allowPrivilegeEscalation - - spec.containers[*].securityContext.procMount - - spec.containers[*].securityContext.runAsUser - - spec.containers[*].securityContext.runAsGroup - properties: - name: - description: |- - Name is the name of the operating system. The currently supported values are linux and windows. - Additional value may be defined in future and can be one of: - https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration - Clients should expect to handle additional values and treat unrecognized values in this field as os: null - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - This field will be autopopulated at admission time by the RuntimeClass admission controller. If - the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - The RuntimeClass admission controller will reject Pod create requests which have the overhead already - set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - type: object - podDisruptionBudget: - description: |- - Defines the Kubernetes PodDisruptionBudgetSpec for this service. When configured, the SonataFlowPlatform controller - will automatically create a PodDisruptionBudget based on this specification that targets the service Deployment. - Currently only apply for the Data Index. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at most "maxUnavailable" pods selected by - "selector" are unavailable after the eviction, i.e. even in absence of - the evicted pod. For example, one can prevent all voluntary evictions - by specifying 0. This is a mutually exclusive setting with "minAvailable". - x-kubernetes-int-or-string: true - minAvailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at least "minAvailable" pods selected by - "selector" will still be available after the eviction, i.e. even in the - absence of the evicted pod. So for example you can prevent all voluntary - evictions by specifying "100%". This is a mutually exclusive setting with "maxUnavailable". - x-kubernetes-int-or-string: true - type: object - preemptionPolicy: - description: |- - PreemptionPolicy is the Policy for preempting pods with lower priority. - One of Never, PreemptLowerPriority. - Defaults to PreemptLowerPriority if unset. - type: string - priority: - description: |- - The priority value. Various system components use this field to find the - priority of the pod. When Priority Admission Controller is enabled, it - prevents users from setting this field. The admission controller populates - this field from PriorityClassName. - The higher the value, the higher the priority. - format: int32 - type: integer - priorityClassName: - description: |- - If specified, indicates the pod's priority. "system-node-critical" and - "system-cluster-critical" are two special keywords which indicate the - highest priorities with the former being the highest priority. Any other - name must be defined by creating a PriorityClass object with that name. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessGates: - description: |- - If specified, all readiness gates will be evaluated for pod readiness. - A pod is ready when all its containers are ready AND - all conditions specified in the readiness gates have status equal to "True" - More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - items: - description: PodReadinessGate contains the reference - to a pod condition - properties: - conditionType: - description: ConditionType refers to a condition - in the pod's condition list with matching type. - type: string - required: - - conditionType - type: object - type: array - replicas: - format: int32 - type: integer - resourceClaims: - description: |- - ResourceClaims defines which ResourceClaims must be allocated - and reserved before the Pod is allowed to start. The resources - will be made available to those containers which consume them - by name. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. - items: - description: |- - PodResourceClaim references exactly one ResourceClaim, either directly - or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim - for the pod. - - It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. - Containers that need access to the ResourceClaim reference it with this name. - properties: - name: - description: |- - Name uniquely identifies this resource claim inside the pod. - This must be a DNS_LABEL. - type: string - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. - - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. - - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restartPolicy: - description: |- - Restart policy for all containers within the pod. - One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - Default to Always. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - type: string - runtimeClassName: - description: |- - RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - empty definition that uses the default runtime handler. - More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - type: string - schedulerName: - description: |- - If specified, the pod will be dispatched by specified scheduler. - If not specified, the pod will be dispatched by default scheduler. - type: string - schedulingGates: - description: |- - SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - scheduler will not attempt to schedule the pod. - - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. - items: - description: PodSchedulingGate is associated to a Pod - to guard its scheduling. - properties: - name: - description: |- - Name of the scheduling gate. - Each scheduling gate must have a unique name field. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - description: |- - SecurityContext holds pod-level security attributes and common container settings. - Optional: Defaults to empty. See type description for default values of each field. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that - applies to the container. - type: string - role: - description: Role is a SELinux role label that - applies to the container. - type: string - type: - description: Type is a SELinux type label that - applies to the container. - type: string - user: - description: User is a SELinux user label that - applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the ServiceAccount to use to run this pod. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - setHostnameAsFQDN: - description: |- - If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - If a pod does not have FQDN, this has no effect. - Default to false. - type: boolean - shareProcessNamespace: - description: |- - Share a single process namespace between all of the containers in a pod. - When this is set containers will be able to view and signal processes from other containers - in the same pod, and the first process in each container will not be assigned PID 1. - HostPID and ShareProcessNamespace cannot both be set. - Optional: Default to false. - type: boolean - subdomain: - description: |- - If specified, the fully qualified Pod hostname will be "...svc.". - If not specified, the pod will not have a domainname at all. - type: string - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - If this value is nil, the default grace period will be used instead. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - Defaults to 30 seconds. - format: int64 - type: integer - tolerations: - description: If specified, the pod's tolerations. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of pods ought to spread across topology - domains. Scheduler will schedule pods in a way which abides by the constraints. - All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how - to spread matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: |- - List of volumes that can be mounted by containers belonging to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes - items: - description: Volume represents a named volume in a pod - that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data - Disk mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching - mode: None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data - disk in the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk - in the blob storage - type: string - fsType: - default: ext4 - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: - multiple blob disks per storage account Dedicated: - single blob disk per storage account Managed: - azure managed data disk (only in managed availability - set). defaults to shared' - type: string - readOnly: - default: false - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File - Service mount on the host and bind mount to the - pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret - that contains Azure Storage Account Name and - Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on - the host that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - description: 'path is Optional: Used as the - mounted root, rather than the full Ceph tree, - default is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that - should populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API - about the pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API - volume file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name, namespace and uid are supported.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. - Must not be absolute or contain the - ''..'' path. Must be utf-8 encoded. - The first item of the relative path - must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - 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 - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - 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 - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query - over volumes to consider for binding. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding - reference to the PersistentVolume - backing this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource - that is attached to a kubelet's host machine and - then exposed to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - lun: - description: 'lun is Optional: FC target lun - number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target - worldwide names (WWNs)' - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver - to use for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field - holds extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume - attached to a kubelet's host machine. This depends - on the Flocker control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the - dataset. This is unique identifier of a Flocker - dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for - the specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - image: - description: |- - image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. - The volume is resolved at pod startup depending on which PullPolicy value is provided: - - - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - - The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. - A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. - The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. - The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). - The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. - properties: - pullPolicy: - description: |- - Policy for pulling OCI objects. Possible values are: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - type: string - reference: - description: |- - Required: Image or artifact reference to be used. - Behaves in the same way as pod.spec.containers[*].image. - Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether - support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether - support iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified - Name. - type: string - iscsiInterface: - default: default - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun - number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - x-kubernetes-list-type: atomic - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for - iSCSI target and initiator authentication - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets - host machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies - Photon Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a - Portworx volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources - secrets, configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: |- - sources is the list of volume projections. Each entry in this list - handles one source. - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - name: - description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. - type: string - optional: - description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the - volume root to write the bundle. - type: string - signerName: - description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. - type: string - required: - - path - type: object - configMap: - description: configMap information about - the configMap data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key - to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether - the ConfigMap or its keys must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about - the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile - represents information to create - the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects - a field of the pod: only annotations, - labels, name, namespace and - uid are supported.' - properties: - apiVersion: - description: Version of - the schema the FieldPath - is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the - field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path - is the relative path name - of the file to be created. - Must not be absolute or contain - the ''..'' path. Must be utf-8 - encoded. The first item of - the relative path must not - start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container - name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the - output format of the exposed - resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: - resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - secret: - description: secret information about - the secret data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key - to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify - whether the Secret or its key must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to - project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - quobyte: - description: quobyte represents a Quobyte mount - on the host that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references - an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - default: /etc/ceph/keyring - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - default: rbd - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - default: admin - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent - volume attached and mounted on Kubernetes nodes. - properties: - fsType: - default: xfs - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of - the ScaleIO API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of - the ScaleIO Protection Domain for the configured - storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable - SSL communication with Gateway, default false - type: boolean - storageMode: - default: ThinProvisioned - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage - Pool associated with the protection domain. - type: string - system: - description: system is the name of the storage - system as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether - the Secret or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage - Policy Based Management (SPBM) profile ID - associated with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage - Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - sink: - description: Defines the sink where the Jobservice sends events - to - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address - Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme - and non-empty host) pointing to the target or a relative - URI. Relative URIs will be resolved using the base URI - retrieved from Ref. - type: string - type: object - source: - description: Defines the source where the Jobservice receives - events from - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address - Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme - and non-empty host) pointing to the target or a relative - URI. Relative URIs will be resolved using the base URI - retrieved from Ref. - type: string - type: object - type: object - type: object - type: object - status: - description: SonataFlowPlatformStatus defines the observed state of SonataFlowPlatform - properties: - cluster: - description: Cluster what kind of cluster you're running (ie, plain - Kubernetes or OpenShift) - enum: - - kubernetes - - openshift - type: string - clusterPlatformRef: - description: ClusterPlatformRef information related to the (optional) - active SonataFlowClusterPlatform - properties: - name: - description: Name of the active SonataFlowClusterPlatform - type: string - platformRef: - description: PlatformRef displays which SonataFlowPlatform has - been referenced by the active SonataFlowClusterPlatform - properties: - name: - description: Name of the SonataFlowPlatform - type: string - namespace: - description: Namespace of the SonataFlowPlatform - type: string - required: - - name - - namespace - type: object - services: - description: Services displays which cluster-wide services are - being used by this SonataFlowPlatform - properties: - dataIndexRef: - description: DataIndexRef displays information on the cluster-wide - Data Index service - properties: - url: - description: Url displays the base url of the service - type: string - type: object - jobServiceRef: - description: JobServiceRef displays information on the cluster-wide - Job Service - properties: - url: - description: Url displays the base url of the service - type: string - type: object - type: object - type: object - conditions: - description: The latest available observations of a resource's current - state. - items: - description: Condition describes the common structure for conditions - in our types - properties: - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human-readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type condition for the given object - type: string - required: - - status - - type - type: object - type: array - info: - additionalProperties: - type: string - description: Info generic information related to the Platform - type: object - observedGeneration: - description: The generation observed by the deployment controller. - format: int64 - type: integer - sonataFlowPlatformDBMigrationPhase: - properties: - dbMigrationStatus: - type: string - message: - type: string - reason: - type: string - type: object - triggers: - description: Triggers list of triggers created for the SonataFlowPlatform - items: - description: SonataFlowPlatformTriggerRef defines a trigger created - for the SonataFlowPlatform. - properties: - name: - description: Name of the Trigger - type: string - namespace: - description: Namespace of the Trigger - type: string - required: - - name - - namespace - type: object - type: array - version: - description: Version the operator version controlling this Platform - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflows.sonataflow.org -spec: - group: sonataflow.org - names: - kind: SonataFlow - listKind: SonataFlowList - plural: sonataflows - shortNames: - - sf - - workflow - - workflows - singular: sonataflow - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.annotations.sonataflow\.org\/profile - name: Profile - type: string - - jsonPath: .metadata.annotations.sonataflow\.org\/version - name: Version - type: string - - jsonPath: .status.endpoint - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=='Running')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Running')].reason - name: Reason - type: string - name: v1alpha08 - schema: - openAPIV3Schema: - description: SonataFlow is the descriptor representation for a workflow application - based on the CNCF Serverless Workflow specification. - 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: SonataFlowSpec defines the desired state of SonataFlow - properties: - flow: - description: Flow the workflow definition. - properties: - annotations: - description: |- - Annotations List of helpful terms describing the workflows intended purpose, subject areas, or other important - qualities. - items: - type: string - type: array - auth: - description: |- - Auth definitions can be used to define authentication information that should be applied to resources defined - in the operation property of function definitions. It is not used as authentication information for the - function invocation, but just to access the resource containing the function invocation information. - x-kubernetes-preserve-unknown-fields: true - autoRetries: - description: AutoRetries If set to true, actions should automatically - be retried on unchecked errors. Default is false - type: boolean - constants: - additionalProperties: - description: |- - RawMessage is a raw encoded JSON value. - It implements [Marshaler] and [Unmarshaler] and can - be used to delay JSON decoding or precompute a JSON encoding. - format: byte - type: string - description: |- - Constants Workflow constants are used to define static, and immutable, data which is available to - Workflow Expressions. - type: object - dataInputSchema: - description: DataInputSchema URI of the JSON Schema used to validate - the workflow data input - properties: - failOnValidationErrors: - type: boolean - schema: - x-kubernetes-preserve-unknown-fields: true - required: - - failOnValidationErrors - - schema - type: object - errors: - description: Defines checked errors that can be explicitly handled - during workflow execution. - items: - description: Error declaration for workflow definitions - properties: - code: - description: |- - Code OnError code. Can be used in addition to the name to help runtimes resolve to technical errors/exceptions. - Should not be defined if error is set to '*'. - type: string - description: - description: OnError description. - type: string - name: - description: Name Domain-specific error name. - type: string - required: - - name - type: object - type: array - events: - items: - description: Event used to define events and their correlations - properties: - correlation: - description: Define event correlation rules for this event. - Only used for consumed events. - items: - description: Correlation define event correlation rules - for an event. Only used for `consumed` events - properties: - contextAttributeName: - description: CloudEvent Extension Context Attribute - name - type: string - contextAttributeValue: - description: CloudEvent Extension Context Attribute - value - type: string - required: - - contextAttributeName - type: object - type: array - dataOnly: - default: true - description: |- - If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload - and context attributes should be accessible. Defaults to true. - type: boolean - kind: - default: consumed - description: Defines the CloudEvent as either 'consumed' - or 'produced' by the workflow. Defaults to `consumed`. - enum: - - consumed - - produced - type: string - metadata: - description: Metadata information - x-kubernetes-preserve-unknown-fields: true - name: - description: Unique event name. - type: string - source: - description: CloudEvent source. - type: string - type: - description: CloudEvent type. - type: string - required: - - name - - type - type: object - type: array - functions: - items: - description: Function ... - properties: - authRef: - description: References an auth definition name to be used - to access to resource defined in the operation parameter. - type: string - metadata: - description: Metadata information - x-kubernetes-preserve-unknown-fields: true - name: - description: Unique function name - type: string - operation: - description: |- - If type is `rest`, #. - If type is `rpc`, ##. - If type is `expression`, defines the workflow expression. If the type is `custom`, - #. - type: string - type: - default: rest - description: |- - Defines the function type. Is either `custom`, `rest`, `rpc`, `expression`, `graphql`, `odata` or `asyncapi`. - Default is `rest`. - enum: - - rest - - rpc - - expression - - graphql - - odata - - asyncapi - - custom - type: string - required: - - name - - operation - type: object - type: array - keepActive: - description: |- - If "true", workflow instances is not terminated when there are no active execution paths. - Instance can be terminated with "terminate end definition" or reaching defined "workflowExecTimeout" - type: boolean - metadata: - description: Metadata custom information shared with the runtime. - x-kubernetes-preserve-unknown-fields: true - retries: - items: - description: Retry ... - properties: - delay: - description: Time delay between retry attempts (ISO 8601 - duration format) - type: string - increment: - description: Static value by which the delay increases during - each attempt (ISO 8601 time format) - type: string - jitter: - description: If float type, maximum amount of random time - added or subtracted from the delay between each retry - relative to total delay (between 0 and 1). If string type, - absolute maximum amount of random time added or subtracted - from the delay between each retry (ISO 8601 duration format) - properties: - floatVal: - type: number - strVal: - type: string - type: - description: Type represents the stored type of Float32OrString. - format: int64 - type: integer - type: object - maxAttempts: - anyOf: - - type: integer - - type: string - description: Maximum number of retry attempts. - x-kubernetes-int-or-string: true - maxDelay: - description: Maximum time delay between retry attempts (ISO - 8601 duration format) - type: string - multiplier: - description: Numeric value, if specified the delay between - retries is multiplied by this value. - properties: - floatVal: - type: number - strVal: - type: string - type: - description: Type represents the stored type of Float32OrString. - format: int64 - type: integer - type: object - name: - description: Unique retry strategy name - type: string - required: - - maxAttempts - - name - type: object - type: array - secrets: - description: |- - Secrets allow you to access sensitive information, such as passwords, OAuth tokens, ssh keys, etc, - inside your Workflow Expressions. - items: - type: string - type: array - start: - description: Workflow start definition. - x-kubernetes-preserve-unknown-fields: true - states: - items: - properties: - callbackState: - description: callbackState executes a function and waits - for callback event that indicates completion of the task. - properties: - action: - description: Defines the action to be executed. - properties: - actionDataFilter: - description: |- - Filter the state data to select only the data that can be used within function definition arguments - using its fromStateData property. Filter the action results to select only the result data that should - be added/merged back into the state data using its results property. Select the part of state data which - the action data results should be added/merged to using the toStateData property. - properties: - fromStateData: - description: Workflow expression that filters - state data that can be used by the action. - type: string - results: - description: Workflow expression that filters - the actions data results. - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be - added/merged into. If not specified denotes the top-level state data element. - type: string - useResults: - description: |- - If set to false, action data results are not added/merged to state data. In this case 'results' - and 'toStateData' should be ignored. Default is true. - type: boolean - type: object - condition: - description: Expression, if defined, must evaluate - to true for this action to be performed. If false, - action is disregarded. - type: string - eventRef: - description: References a 'trigger' and 'result' - reusable event definitions. - properties: - contextAttributes: - description: Add additional extension context - attributes to the produced event. - x-kubernetes-preserve-unknown-fields: true - data: - description: |- - If string type, an expression which selects parts of the states data output to become the data (payload) - of the event referenced by triggerEventRef. If object type, a custom object to become the data (payload) - of the event referenced by triggerEventRef. - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - resultEventRef: - description: Reference to the unique name of - a 'consumed' event definition - type: string - resultEventTimeout: - description: |- - Maximum amount of time (ISO 8601 format) to wait for the result event. If not defined it be set to the - actionExecutionTimeout - type: string - triggerEventRef: - description: Reference to the unique name of - a 'produced' event definition, - type: string - required: - - triggerEventRef - type: object - functionRef: - description: References a reusable function definition. - properties: - arguments: - description: Arguments (inputs) to be passed - to the referenced function - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - refName: - description: Name of the referenced function. - type: string - selectionSet: - description: Used if function type is graphql. - String containing a valid GraphQL selection - set. - type: string - required: - - refName - type: object - id: - description: Defines Unique action identifier. - type: string - name: - description: Defines Unique action name. - type: string - nonRetryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should not be retried. - Used only when `autoRetries` is set to `true` - items: - type: string - type: array - retryRef: - description: References a defined workflow retry - definition. If not defined uses the default runtime - retry definition. - type: string - retryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should be retried. - Used only when `autoRetries` is set to `false` - items: - type: string - type: array - sleep: - description: Defines time period workflow execution - should sleep before / after function execution. - properties: - after: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep after function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - before: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep before function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - type: object - subFlowRef: - description: References a workflow to be invoked. - properties: - invoke: - default: sync - description: |- - Specifies if the subflow should be invoked sync or async. - Defaults to sync. - enum: - - async - - sync - type: string - onParentComplete: - default: terminate - description: |- - onParentComplete specifies how subflow execution should behave when parent workflow completes if invoke - is 'async'. Defaults to terminate. - enum: - - terminate - - continue - type: string - version: - description: Sub-workflow version - type: string - workflowId: - description: Sub-workflow unique id - type: string - required: - - workflowId - type: object - type: object - eventDataFilter: - description: Event data filter definition. - properties: - data: - description: Workflow expression that filters of - the event data (payload). - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be added/merged into. - If not specified denotes the top-level state data element - type: string - useData: - description: |- - If set to false, event payload is not added/merged to state data. In this case 'data' and 'toStateData' - should be ignored. Default is true. - type: boolean - type: object - eventRef: - description: References a unique callback event name - in the defined workflow events. - type: string - timeouts: - description: Time period to wait for incoming events - (ISO 8601 format) - properties: - actionExecTimeout: - description: Default single actions definition execution - timeout (ISO 8601 duration format) - type: string - eventTimeout: - description: Default timeout for consuming defined - events (ISO 8601 duration format) - type: string - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - action - - eventRef - type: object - compensatedBy: - description: Unique Name of a workflow state which is responsible - for compensation of this state. - type: string - delayState: - description: delayState Causes the workflow execution to - delay for a specified duration. - properties: - timeDelay: - description: Amount of time (ISO 8601 format) to delay - type: string - required: - - timeDelay - type: object - end: - description: State end definition. - x-kubernetes-preserve-unknown-fields: true - eventState: - description: |- - event states await one or more events and perform actions when they are received. If defined as the - workflow starting state, the event state definition controls when the workflow instances should be created. - properties: - exclusive: - default: true - description: |- - If true consuming one of the defined events causes its associated actions to be performed. If false all - the defined events must be consumed in order for actions to be performed. Defaults to true. - type: boolean - onEvents: - description: Define the events to be consumed and optional - actions to be performed. - items: - description: OnEvents define which actions are be - performed for the one or more events. - properties: - actionMode: - default: sequential - description: Should actions be performed sequentially - or in parallel. Default is sequential. - enum: - - sequential - - parallel - type: string - actions: - description: Actions to be performed if expression - matches - items: - description: Action specify invocations of services - or other workflows during workflow execution. - properties: - actionDataFilter: - description: |- - Filter the state data to select only the data that can be used within function definition arguments - using its fromStateData property. Filter the action results to select only the result data that should - be added/merged back into the state data using its results property. Select the part of state data which - the action data results should be added/merged to using the toStateData property. - properties: - fromStateData: - description: Workflow expression that - filters state data that can be used - by the action. - type: string - results: - description: Workflow expression that - filters the actions data results. - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be - added/merged into. If not specified denotes the top-level state data element. - type: string - useResults: - description: |- - If set to false, action data results are not added/merged to state data. In this case 'results' - and 'toStateData' should be ignored. Default is true. - type: boolean - type: object - condition: - description: Expression, if defined, must - evaluate to true for this action to be - performed. If false, action is disregarded. - type: string - eventRef: - description: References a 'trigger' and - 'result' reusable event definitions. - properties: - contextAttributes: - description: Add additional extension - context attributes to the produced - event. - x-kubernetes-preserve-unknown-fields: true - data: - description: |- - If string type, an expression which selects parts of the states data output to become the data (payload) - of the event referenced by triggerEventRef. If object type, a custom object to become the data (payload) - of the event referenced by triggerEventRef. - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function - should be invoked sync or async. Default - is sync. - enum: - - async - - sync - type: string - resultEventRef: - description: Reference to the unique - name of a 'consumed' event definition - type: string - resultEventTimeout: - description: |- - Maximum amount of time (ISO 8601 format) to wait for the result event. If not defined it be set to the - actionExecutionTimeout - type: string - triggerEventRef: - description: Reference to the unique - name of a 'produced' event definition, - type: string - required: - - triggerEventRef - type: object - functionRef: - description: References a reusable function - definition. - properties: - arguments: - description: Arguments (inputs) to be - passed to the referenced function - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function - should be invoked sync or async. Default - is sync. - enum: - - async - - sync - type: string - refName: - description: Name of the referenced - function. - type: string - selectionSet: - description: Used if function type is - graphql. String containing a valid - GraphQL selection set. - type: string - required: - - refName - type: object - id: - description: Defines Unique action identifier. - type: string - name: - description: Defines Unique action name. - type: string - nonRetryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should not be retried. - Used only when `autoRetries` is set to `true` - items: - type: string - type: array - retryRef: - description: References a defined workflow - retry definition. If not defined uses - the default runtime retry definition. - type: string - retryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should be retried. - Used only when `autoRetries` is set to `false` - items: - type: string - type: array - sleep: - description: Defines time period workflow - execution should sleep before / after - function execution. - properties: - after: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep after function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - before: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep before function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - type: object - subFlowRef: - description: References a workflow to be - invoked. - properties: - invoke: - default: sync - description: |- - Specifies if the subflow should be invoked sync or async. - Defaults to sync. - enum: - - async - - sync - type: string - onParentComplete: - default: terminate - description: |- - onParentComplete specifies how subflow execution should behave when parent workflow completes if invoke - is 'async'. Defaults to terminate. - enum: - - terminate - - continue - type: string - version: - description: Sub-workflow version - type: string - workflowId: - description: Sub-workflow unique id - type: string - required: - - workflowId - type: object - type: object - type: array - eventDataFilter: - description: eventDataFilter defines the callback - event data filter definition - properties: - data: - description: Workflow expression that filters - of the event data (payload). - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be added/merged into. - If not specified denotes the top-level state data element - type: string - useData: - description: |- - If set to false, event payload is not added/merged to state data. In this case 'data' and 'toStateData' - should be ignored. Default is true. - type: boolean - type: object - eventRefs: - description: References one or more unique event - names in the defined workflow events. - items: - type: string - minItems: 1 - type: array - required: - - eventRefs - type: object - minItems: 1 - type: array - timeouts: - description: State specific timeouts. - properties: - actionExecTimeout: - description: Default single actions definition execution - timeout (ISO 8601 duration format) - type: string - eventTimeout: - description: Default timeout for consuming defined - events (ISO 8601 duration format) - type: string - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - onEvents - type: object - forEachState: - description: forEachState used to execute actions for each - element of a data set. - properties: - actions: - description: Actions to be executed for each of the - elements of inputCollection. - items: - description: Action specify invocations of services - or other workflows during workflow execution. - properties: - actionDataFilter: - description: |- - Filter the state data to select only the data that can be used within function definition arguments - using its fromStateData property. Filter the action results to select only the result data that should - be added/merged back into the state data using its results property. Select the part of state data which - the action data results should be added/merged to using the toStateData property. - properties: - fromStateData: - description: Workflow expression that filters - state data that can be used by the action. - type: string - results: - description: Workflow expression that filters - the actions data results. - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be - added/merged into. If not specified denotes the top-level state data element. - type: string - useResults: - description: |- - If set to false, action data results are not added/merged to state data. In this case 'results' - and 'toStateData' should be ignored. Default is true. - type: boolean - type: object - condition: - description: Expression, if defined, must evaluate - to true for this action to be performed. If - false, action is disregarded. - type: string - eventRef: - description: References a 'trigger' and 'result' - reusable event definitions. - properties: - contextAttributes: - description: Add additional extension context - attributes to the produced event. - x-kubernetes-preserve-unknown-fields: true - data: - description: |- - If string type, an expression which selects parts of the states data output to become the data (payload) - of the event referenced by triggerEventRef. If object type, a custom object to become the data (payload) - of the event referenced by triggerEventRef. - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - resultEventRef: - description: Reference to the unique name - of a 'consumed' event definition - type: string - resultEventTimeout: - description: |- - Maximum amount of time (ISO 8601 format) to wait for the result event. If not defined it be set to the - actionExecutionTimeout - type: string - triggerEventRef: - description: Reference to the unique name - of a 'produced' event definition, - type: string - required: - - triggerEventRef - type: object - functionRef: - description: References a reusable function definition. - properties: - arguments: - description: Arguments (inputs) to be passed - to the referenced function - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - refName: - description: Name of the referenced function. - type: string - selectionSet: - description: Used if function type is graphql. - String containing a valid GraphQL selection - set. - type: string - required: - - refName - type: object - id: - description: Defines Unique action identifier. - type: string - name: - description: Defines Unique action name. - type: string - nonRetryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should not be retried. - Used only when `autoRetries` is set to `true` - items: - type: string - type: array - retryRef: - description: References a defined workflow retry - definition. If not defined uses the default - runtime retry definition. - type: string - retryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should be retried. - Used only when `autoRetries` is set to `false` - items: - type: string - type: array - sleep: - description: Defines time period workflow execution - should sleep before / after function execution. - properties: - after: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep after function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - before: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep before function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - type: object - subFlowRef: - description: References a workflow to be invoked. - properties: - invoke: - default: sync - description: |- - Specifies if the subflow should be invoked sync or async. - Defaults to sync. - enum: - - async - - sync - type: string - onParentComplete: - default: terminate - description: |- - onParentComplete specifies how subflow execution should behave when parent workflow completes if invoke - is 'async'. Defaults to terminate. - enum: - - terminate - - continue - type: string - version: - description: Sub-workflow version - type: string - workflowId: - description: Sub-workflow unique id - type: string - required: - - workflowId - type: object - type: object - minItems: 0 - type: array - batchSize: - anyOf: - - type: integer - - type: string - description: |- - Specifies how many iterations may run in parallel at the same time. Used if mode property is set to - parallel (default). If not specified, its value should be the size of the inputCollection. - x-kubernetes-int-or-string: true - inputCollection: - description: Workflow expression selecting an array - element of the states' data. - type: string - iterationParam: - description: |- - Name of the iteration parameter that can be referenced in actions/workflow. For each parallel iteration, - this param should contain a unique element of the inputCollection array. - type: string - mode: - default: parallel - description: Specifies how iterations are to be performed - (sequential or in parallel), defaults to parallel. - enum: - - sequential - - parallel - type: string - outputCollection: - description: Workflow expression specifying an array - element of the states data to add the results of each - iteration. - type: string - timeouts: - description: State specific timeout. - properties: - actionExecTimeout: - description: Default single actions definition execution - timeout (ISO 8601 duration format) - type: string - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - inputCollection - type: object - id: - description: Unique State id. - type: string - injectState: - description: injectState used to inject static data into - state data input. - properties: - data: - description: JSON object which can be set as state's - data input and can be manipulated via filter - x-kubernetes-preserve-unknown-fields: true - timeouts: - description: State specific timeouts - properties: - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - data - type: object - metadata: - description: Metadata information. - x-kubernetes-preserve-unknown-fields: true - name: - description: State name. - type: string - onErrors: - description: States error handling and retries definitions. - items: - description: OnError ... - properties: - end: - description: |- - End workflow execution in case of this error. If retryRef is defined, this ends workflow only if - retries were unsuccessful. - x-kubernetes-preserve-unknown-fields: true - errorRef: - description: ErrorRef Reference to a unique workflow - error definition. Used of errorRefs is not used - type: string - errorRefs: - description: ErrorRefs References one or more workflow - error definitions. Used if errorRef is not used - items: - type: string - type: array - transition: - description: |- - Transition to next state to handle the error. If retryRef is defined, this transition is taken only if - retries were unsuccessful. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - operationState: - description: operationState defines a set of actions to - be performed in sequence or in parallel. - properties: - actionMode: - default: sequential - description: Specifies whether actions are performed - in sequence or in parallel, defaults to sequential. - enum: - - sequential - - parallel - type: string - actions: - description: Actions to be performed - items: - description: Action specify invocations of services - or other workflows during workflow execution. - properties: - actionDataFilter: - description: |- - Filter the state data to select only the data that can be used within function definition arguments - using its fromStateData property. Filter the action results to select only the result data that should - be added/merged back into the state data using its results property. Select the part of state data which - the action data results should be added/merged to using the toStateData property. - properties: - fromStateData: - description: Workflow expression that filters - state data that can be used by the action. - type: string - results: - description: Workflow expression that filters - the actions data results. - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be - added/merged into. If not specified denotes the top-level state data element. - type: string - useResults: - description: |- - If set to false, action data results are not added/merged to state data. In this case 'results' - and 'toStateData' should be ignored. Default is true. - type: boolean - type: object - condition: - description: Expression, if defined, must evaluate - to true for this action to be performed. If - false, action is disregarded. - type: string - eventRef: - description: References a 'trigger' and 'result' - reusable event definitions. - properties: - contextAttributes: - description: Add additional extension context - attributes to the produced event. - x-kubernetes-preserve-unknown-fields: true - data: - description: |- - If string type, an expression which selects parts of the states data output to become the data (payload) - of the event referenced by triggerEventRef. If object type, a custom object to become the data (payload) - of the event referenced by triggerEventRef. - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - resultEventRef: - description: Reference to the unique name - of a 'consumed' event definition - type: string - resultEventTimeout: - description: |- - Maximum amount of time (ISO 8601 format) to wait for the result event. If not defined it be set to the - actionExecutionTimeout - type: string - triggerEventRef: - description: Reference to the unique name - of a 'produced' event definition, - type: string - required: - - triggerEventRef - type: object - functionRef: - description: References a reusable function definition. - properties: - arguments: - description: Arguments (inputs) to be passed - to the referenced function - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function should - be invoked sync or async. Default is sync. - enum: - - async - - sync - type: string - refName: - description: Name of the referenced function. - type: string - selectionSet: - description: Used if function type is graphql. - String containing a valid GraphQL selection - set. - type: string - required: - - refName - type: object - id: - description: Defines Unique action identifier. - type: string - name: - description: Defines Unique action name. - type: string - nonRetryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should not be retried. - Used only when `autoRetries` is set to `true` - items: - type: string - type: array - retryRef: - description: References a defined workflow retry - definition. If not defined uses the default - runtime retry definition. - type: string - retryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should be retried. - Used only when `autoRetries` is set to `false` - items: - type: string - type: array - sleep: - description: Defines time period workflow execution - should sleep before / after function execution. - properties: - after: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep after function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - before: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep before function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - type: object - subFlowRef: - description: References a workflow to be invoked. - properties: - invoke: - default: sync - description: |- - Specifies if the subflow should be invoked sync or async. - Defaults to sync. - enum: - - async - - sync - type: string - onParentComplete: - default: terminate - description: |- - onParentComplete specifies how subflow execution should behave when parent workflow completes if invoke - is 'async'. Defaults to terminate. - enum: - - terminate - - continue - type: string - version: - description: Sub-workflow version - type: string - workflowId: - description: Sub-workflow unique id - type: string - required: - - workflowId - type: object - type: object - minItems: 0 - type: array - timeouts: - description: State specific timeouts - properties: - actionExecTimeout: - description: Default single actions definition execution - timeout (ISO 8601 duration format) - type: string - stateExecTimeout: - description: Defines workflow state execution timeout. - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - actions - type: object - parallelState: - description: parallelState Consists of a number of states - that are executed in parallel. - properties: - branches: - description: List of branches for this parallel state. - items: - description: Branch Definition - properties: - actions: - description: Actions to be executed in this branch - items: - description: Action specify invocations of services - or other workflows during workflow execution. - properties: - actionDataFilter: - description: |- - Filter the state data to select only the data that can be used within function definition arguments - using its fromStateData property. Filter the action results to select only the result data that should - be added/merged back into the state data using its results property. Select the part of state data which - the action data results should be added/merged to using the toStateData property. - properties: - fromStateData: - description: Workflow expression that - filters state data that can be used - by the action. - type: string - results: - description: Workflow expression that - filters the actions data results. - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be - added/merged into. If not specified denotes the top-level state data element. - type: string - useResults: - description: |- - If set to false, action data results are not added/merged to state data. In this case 'results' - and 'toStateData' should be ignored. Default is true. - type: boolean - type: object - condition: - description: Expression, if defined, must - evaluate to true for this action to be - performed. If false, action is disregarded. - type: string - eventRef: - description: References a 'trigger' and - 'result' reusable event definitions. - properties: - contextAttributes: - description: Add additional extension - context attributes to the produced - event. - x-kubernetes-preserve-unknown-fields: true - data: - description: |- - If string type, an expression which selects parts of the states data output to become the data (payload) - of the event referenced by triggerEventRef. If object type, a custom object to become the data (payload) - of the event referenced by triggerEventRef. - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function - should be invoked sync or async. Default - is sync. - enum: - - async - - sync - type: string - resultEventRef: - description: Reference to the unique - name of a 'consumed' event definition - type: string - resultEventTimeout: - description: |- - Maximum amount of time (ISO 8601 format) to wait for the result event. If not defined it be set to the - actionExecutionTimeout - type: string - triggerEventRef: - description: Reference to the unique - name of a 'produced' event definition, - type: string - required: - - triggerEventRef - type: object - functionRef: - description: References a reusable function - definition. - properties: - arguments: - description: Arguments (inputs) to be - passed to the referenced function - x-kubernetes-preserve-unknown-fields: true - invoke: - default: sync - description: Specifies if the function - should be invoked sync or async. Default - is sync. - enum: - - async - - sync - type: string - refName: - description: Name of the referenced - function. - type: string - selectionSet: - description: Used if function type is - graphql. String containing a valid - GraphQL selection set. - type: string - required: - - refName - type: object - id: - description: Defines Unique action identifier. - type: string - name: - description: Defines Unique action name. - type: string - nonRetryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should not be retried. - Used only when `autoRetries` is set to `true` - items: - type: string - type: array - retryRef: - description: References a defined workflow - retry definition. If not defined uses - the default runtime retry definition. - type: string - retryableErrors: - description: |- - List of unique references to defined workflow errors for which the action should be retried. - Used only when `autoRetries` is set to `false` - items: - type: string - type: array - sleep: - description: Defines time period workflow - execution should sleep before / after - function execution. - properties: - after: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep after function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - before: - description: |- - Defines amount of time (ISO 8601 duration format) to sleep before function/subflow invocation. - Does not apply if 'eventRef' is defined. - type: string - type: object - subFlowRef: - description: References a workflow to be - invoked. - properties: - invoke: - default: sync - description: |- - Specifies if the subflow should be invoked sync or async. - Defaults to sync. - enum: - - async - - sync - type: string - onParentComplete: - default: terminate - description: |- - onParentComplete specifies how subflow execution should behave when parent workflow completes if invoke - is 'async'. Defaults to terminate. - enum: - - terminate - - continue - type: string - version: - description: Sub-workflow version - type: string - workflowId: - description: Sub-workflow unique id - type: string - required: - - workflowId - type: object - type: object - minItems: 1 - type: array - name: - description: Branch name - type: string - timeouts: - description: Branch specific timeout settings - properties: - actionExecTimeout: - description: Single actions definition execution - timeout duration (ISO 8601 duration format) - type: string - branchExecTimeout: - description: Single branch execution timeout - duration (ISO 8601 duration format) - type: string - type: object - required: - - actions - - name - type: object - minItems: 1 - type: array - completionType: - default: allOf - description: Option types on how to complete branch - execution. Defaults to `allOf`. - enum: - - allOf - - atLeast - type: string - numCompleted: - anyOf: - - type: integer - - type: string - description: |- - Used when branchCompletionType is set to atLeast to specify the least number of branches that must complete - in order for the state to transition/end. - x-kubernetes-int-or-string: true - timeouts: - description: State specific timeouts - properties: - branchExecTimeout: - description: Default single branch execution timeout - (ISO 8601 duration format) - type: string - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - branches - type: object - sleepState: - description: sleepState suspends workflow execution for - a given time duration. - properties: - duration: - description: Duration (ISO 8601 duration format) to - sleep - type: string - timeouts: - description: Timeouts State specific timeouts - properties: - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - duration - type: object - stateDataFilter: - description: State data filter. - properties: - input: - description: Workflow expression to filter the state - data input - type: string - output: - description: Workflow expression that filters the state - data output - type: string - type: object - switchState: - description: 'switchState is workflow''s gateways: direct - transitions onf a workflow based on certain conditions.' - properties: - dataConditions: - description: Defines conditions evaluated against data - items: - description: |- - DataCondition specify a data-based condition statement which causes a transition to another workflow state - if evaluated to true. - properties: - condition: - description: Workflow expression evaluated against - state data. Must evaluate to true or false. - type: string - end: - description: Explicit transition to end - properties: - compensate: - description: If set to true, triggers workflow - compensation before workflow execution completes. - Default is false. - type: boolean - continueAs: - description: |- - Defines that current workflow execution should stop, and execution should continue as a new workflow - instance of the provided id - properties: - data: - description: |- - If string type, an expression which selects parts of the states data output to become the workflow data input of - continued execution. If object type, a custom object to become the workflow data input of the continued execution - x-kubernetes-preserve-unknown-fields: true - version: - description: Version of the workflow to - continue execution as. - type: string - workflowExecTimeout: - description: |- - WorkflowExecTimeout Workflow execution timeout to be used by the workflow continuing execution. - Overwrites any specific settings set by that workflow - properties: - duration: - default: unlimited - description: Workflow execution timeout - duration (ISO 8601 duration format). - If not specified should be 'unlimited'. - type: string - interrupt: - description: |- - If false, workflow instance is allowed to finish current execution. If true, current workflow execution - is stopped immediately. Default is false. - type: boolean - runBefore: - description: Name of a workflow state - to be executed before workflow instance - is terminated. - type: string - required: - - duration - type: object - workflowId: - description: Unique id of the workflow - to continue execution as. - type: string - required: - - workflowId - type: object - produceEvents: - description: Array of producedEvent definitions. - Defines events that should be produced. - items: - description: |- - ProduceEvent Defines the event (CloudEvent format) to be produced when workflow execution completes or during a - workflow transitions. The eventRef property must match the name of one of the defined produced events in the - events definition. - properties: - contextAttributes: - additionalProperties: - type: string - description: Add additional event extension - context attributes. - type: object - data: - description: |- - If String, expression which selects parts of the states data output to become the data of the produced event. - If object a custom object to become the data of produced event. - x-kubernetes-preserve-unknown-fields: true - eventRef: - description: Reference to a defined - unique event name in the events definition - type: string - required: - - eventRef - type: object - type: array - terminate: - description: If true, completes all execution - flows in the given workflow instance. - type: boolean - type: object - metadata: - description: Metadata information. - x-kubernetes-preserve-unknown-fields: true - name: - description: Data condition name. - type: string - transition: - description: Workflow transition if condition - is evaluated to true - properties: - compensate: - default: false - description: If set to true, triggers workflow - compensation before this transition is taken. - Default is false. - type: boolean - nextState: - description: Name of the state to transition - to next. - type: string - produceEvents: - description: Array of producedEvent definitions. - Events to be produced before the transition - takes place. - items: - description: |- - ProduceEvent Defines the event (CloudEvent format) to be produced when workflow execution completes or during a - workflow transitions. The eventRef property must match the name of one of the defined produced events in the - events definition. - properties: - contextAttributes: - additionalProperties: - type: string - description: Add additional event extension - context attributes. - type: object - data: - description: |- - If String, expression which selects parts of the states data output to become the data of the produced event. - If object a custom object to become the data of produced event. - x-kubernetes-preserve-unknown-fields: true - eventRef: - description: Reference to a defined - unique event name in the events definition - type: string - required: - - eventRef - type: object - type: array - required: - - nextState - type: object - required: - - condition - - end - type: object - type: array - defaultCondition: - description: |- - Default transition of the workflow if there is no matching data conditions. Can include a transition or - end definition. - properties: - end: - description: "\tIf this state an end state" - x-kubernetes-preserve-unknown-fields: true - transition: - description: |- - Serverless workflow states can have one or more incoming and outgoing transitions (from/to other states). - Each state can define a transition definition that is used to determine which state to transition to next. - x-kubernetes-preserve-unknown-fields: true - type: object - eventConditions: - description: Defines conditions evaluated against events. - items: - description: EventCondition specify events which the - switch state must wait for. - properties: - end: - description: Explicit transition to end - x-kubernetes-preserve-unknown-fields: true - eventDataFilter: - description: Event data filter definition. - properties: - data: - description: Workflow expression that filters - of the event data (payload). - type: string - toStateData: - description: |- - Workflow expression that selects a state data element to which the action results should be added/merged into. - If not specified denotes the top-level state data element - type: string - useData: - description: |- - If set to false, event payload is not added/merged to state data. In this case 'data' and 'toStateData' - should be ignored. Default is true. - type: boolean - type: object - eventRef: - description: References a unique event name in - the defined workflow events. - type: string - metadata: - description: Metadata information. - x-kubernetes-preserve-unknown-fields: true - name: - description: Event condition name. - type: string - transition: - description: Workflow transition if condition - is evaluated to true - x-kubernetes-preserve-unknown-fields: true - required: - - eventRef - type: object - type: array - timeouts: - description: SwitchState specific timeouts - properties: - eventTimeout: - description: |- - Specify the expire value to transitions to defaultCondition. When event-based conditions do not arrive. - NOTE: this is only available for EventConditions - type: string - stateExecTimeout: - description: Default workflow state execution timeout - (ISO 8601 duration format) - properties: - single: - description: Single state execution timeout, - not including retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, - including retries (ISO 8601 duration format) - type: string - required: - - total - type: object - type: object - required: - - defaultCondition - type: object - transition: - description: Next transition of the workflow after the time - delay. - x-kubernetes-preserve-unknown-fields: true - type: - description: stateType can be any of delay, callback, event, - foreach, inject, operation, parallel, sleep, switch - enum: - - delay - - callback - - event - - foreach - - inject - - operation - - parallel - - sleep - - switch - type: string - usedForCompensation: - description: If true, this state is used to compensate another - state. Default is false. - type: boolean - required: - - name - - type - type: object - minItems: 1 - type: array - x-kubernetes-preserve-unknown-fields: true - timeouts: - description: Defines the workflow default timeout settings. - properties: - actionExecTimeout: - description: ActionExecTimeout Single actions definition execution - timeout duration (ISO 8601 duration format). - type: string - branchExecTimeout: - description: BranchExecTimeout Single branch execution timeout - duration (ISO 8601 duration format). - type: string - eventTimeout: - description: EventTimeout Timeout duration to wait for consuming - defined events (ISO 8601 duration format). - type: string - stateExecTimeout: - description: StateExecTimeout Total state execution timeout - (including retries) (ISO 8601 duration format). - properties: - single: - description: Single state execution timeout, not including - retries (ISO 8601 duration format) - type: string - total: - description: Total state execution timeout, including - retries (ISO 8601 duration format) - type: string - required: - - total - type: object - workflowExecTimeout: - description: |- - WorkflowExecTimeout Workflow execution timeout duration (ISO 8601 duration format). If not specified should - be 'unlimited'. - properties: - duration: - default: unlimited - description: Workflow execution timeout duration (ISO - 8601 duration format). If not specified should be 'unlimited'. - type: string - interrupt: - description: |- - If false, workflow instance is allowed to finish current execution. If true, current workflow execution - is stopped immediately. Default is false. - type: boolean - runBefore: - description: Name of a workflow state to be executed before - workflow instance is terminated. - type: string - required: - - duration - type: object - type: object - required: - - states - type: object - persistence: - description: Persistence defines the database persistence configuration - for the workflow - maxProperties: 2 - properties: - dbMigrationStrategy: - default: service - description: |- - DB Migration approach for data-index and jobs-service. Use the following values as described. - job: use job based approach provided by the SonataFlow operator. - service: service itself shall migrate the db and will not use SonataFlow operator. - none: no database migration functionality needed. - type: string - postgresql: - description: Connect configured services to a postgresql database. - maxProperties: 2 - minProperties: 2 - properties: - jdbcUrl: - description: |- - PostgreSql JDBC URL. Mutually exclusive to serviceRef. - e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - type: string - secretRef: - description: Secret reference to the database user credentials - properties: - name: - description: Name of the postgresql credentials secret. - type: string - passwordKey: - description: Defaults to POSTGRESQL_PASSWORD - type: string - userKey: - description: Defaults to POSTGRESQL_USER - type: string - required: - - name - type: object - serviceRef: - description: Service reference to postgresql datasource. Mutually - exclusive to jdbcUrl. - properties: - databaseName: - description: Name of postgresql database to be used. Defaults - to "sonataflow" - type: string - databaseSchema: - description: Schema of postgresql database to be used. - Defaults to "data-index-service" - type: string - name: - description: Name of the postgresql k8s service. - type: string - namespace: - description: Namespace of the postgresql k8s service. - Defaults to the SonataFlowPlatform's local namespace. - type: string - port: - description: Port to use when connecting to the postgresql - k8s service. Defaults to 5432. - type: integer - required: - - name - type: object - required: - - secretRef - type: object - type: object - podTemplate: - description: PodTemplate describes the deployment details of this - SonataFlow instance. - properties: - activeDeadlineSeconds: - description: |- - Optional duration in seconds the pod may be active on the node relative to - StartTime before the system will actively try to mark it failed and kill associated containers. - Value must be a positive integer. - format: int64 - type: integer - affinity: - description: If specified, the pod's scheduling constraints - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - 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. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - 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. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - automountServiceAccountToken: - description: AutomountServiceAccountToken indicates whether a - service account token should be automatically mounted. - type: boolean - container: - description: |- - Container is the Kubernetes container where the application should run. - One can change this attribute in order to override the defaults provided by the operator. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source of a set - of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request to - perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that the - container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request to - perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that the - container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving a - TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network port in - a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port - to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving a - TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource resize - policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of - the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving a - TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to - be used by the container. - items: - description: volumeDevice describes a mapping of a raw block - device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container - that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume - within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - type: object - containers: - description: |- - List of containers belonging to the pod. - Containers cannot currently be added or removed. - There must be at least one container in a Pod. - Cannot be updated. - items: - description: A single application container that you want to - run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source of a - set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that - the container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that - the container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network port in - a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port - to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of a raw - block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the - container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume - within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - deploymentModel: - description: Defines the kind of deployment model for this pod - spec. In dev profile, only "kubernetes" is valid. - enum: - - kubernetes - - knative - type: string - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS resolver options - of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - enableServiceLinks: - description: |- - EnableServiceLinks indicates whether information about services should be injected into pod's - environment variables, matching the syntax of Docker links. - Optional: Defaults to true. - type: boolean - hostAliases: - description: |- - HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. - items: - description: |- - HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the - pod's hosts file. - properties: - hostnames: - description: Hostnames for the above IP address. - items: - type: string - type: array - x-kubernetes-list-type: atomic - ip: - description: IP address of the host file entry. - type: string - required: - - ip - type: object - type: array - hostIPC: - description: |- - Use the host's ipc namespace. - Optional: Default to false. - type: boolean - hostNetwork: - description: |- - Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. - Default to false. - type: boolean - hostPID: - description: |- - Use the host's pid namespace. - Optional: Default to false. - type: boolean - hostUsers: - description: |- - Use the host's user namespace. - Optional: Default to true. - If set to true or not present, the pod will be run in the host user namespace, useful - for when the pod needs a feature only available to the host user namespace, such as - loading a kernel module with CAP_SYS_MODULE. - When set to false, a new userns is created for the pod. Setting false is useful for - mitigating container breakout vulnerabilities even allowing users to run their - containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - type: boolean - hostname: - description: |- - Specifies the hostname of the Pod - If not specified, the pod's hostname will be set to a system-defined value. - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: |- - List of initialization containers belonging to the pod. - Init containers are executed in order prior to containers being started. If any - init container fails, the pod is considered to have failed and is handled according - to its restartPolicy. The name for an init container or normal container must be - unique among all containers. - Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - The resourceRequirements of an init container are taken into account during scheduling - by finding the highest request/limit for each resource type, and then using the max of - of that value or the sum of the normal containers. Limits are applied to init containers - in a similar fashion. - Init containers cannot currently be added or removed. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - items: - description: A single application container that you want to - run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source of a - set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that - the container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents the duration that - the container should sleep before being terminated. - properties: - seconds: - description: Seconds is the number of seconds - to sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network port in - a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port - to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving a GRPC - port. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of a raw - block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the - container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume - within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - nodeName: - description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - 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/ - type: object - x-kubernetes-map-type: atomic - os: - description: |- - Specifies the OS of the containers in the pod. - Some pod and container fields are restricted if this is set. - - If the OS field is set to linux, the following fields must be unset: - -securityContext.windowsOptions - - If the OS field is set to windows, following fields must be unset: - - spec.hostPID - - spec.hostIPC - - spec.hostUsers - - spec.securityContext.seLinuxOptions - - spec.securityContext.seccompProfile - - spec.securityContext.fsGroup - - spec.securityContext.fsGroupChangePolicy - - spec.securityContext.sysctls - - spec.shareProcessNamespace - - spec.securityContext.runAsUser - - spec.securityContext.runAsGroup - - spec.securityContext.supplementalGroups - - spec.containers[*].securityContext.seLinuxOptions - - spec.containers[*].securityContext.seccompProfile - - spec.containers[*].securityContext.capabilities - - spec.containers[*].securityContext.readOnlyRootFilesystem - - spec.containers[*].securityContext.privileged - - spec.containers[*].securityContext.allowPrivilegeEscalation - - spec.containers[*].securityContext.procMount - - spec.containers[*].securityContext.runAsUser - - spec.containers[*].securityContext.runAsGroup - properties: - name: - description: |- - Name is the name of the operating system. The currently supported values are linux and windows. - Additional value may be defined in future and can be one of: - https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration - Clients should expect to handle additional values and treat unrecognized values in this field as os: null - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - This field will be autopopulated at admission time by the RuntimeClass admission controller. If - the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - The RuntimeClass admission controller will reject Pod create requests which have the overhead already - set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - type: object - podDisruptionBudget: - description: |- - Defines the Kubernetes PodDisruptionBudgetSpec for this workflow. When configured, the SonataFlow controller will - automatically create a PodDisruptionBudget based on this specification that targets the workflow Deployment. - Ignored in "knative" deployment model, and dev profile workflows. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at most "maxUnavailable" pods selected by - "selector" are unavailable after the eviction, i.e. even in absence of - the evicted pod. For example, one can prevent all voluntary evictions - by specifying 0. This is a mutually exclusive setting with "minAvailable". - x-kubernetes-int-or-string: true - minAvailable: - anyOf: - - type: integer - - type: string - description: |- - An eviction is allowed if at least "minAvailable" pods selected by - "selector" will still be available after the eviction, i.e. even in the - absence of the evicted pod. So for example you can prevent all voluntary - evictions by specifying "100%". This is a mutually exclusive setting with "maxUnavailable". - x-kubernetes-int-or-string: true - type: object - preemptionPolicy: - description: |- - PreemptionPolicy is the Policy for preempting pods with lower priority. - One of Never, PreemptLowerPriority. - Defaults to PreemptLowerPriority if unset. - type: string - priority: - description: |- - The priority value. Various system components use this field to find the - priority of the pod. When Priority Admission Controller is enabled, it - prevents users from setting this field. The admission controller populates - this field from PriorityClassName. - The higher the value, the higher the priority. - format: int32 - type: integer - priorityClassName: - description: |- - If specified, indicates the pod's priority. "system-node-critical" and - "system-cluster-critical" are two special keywords which indicate the - highest priorities with the former being the highest priority. Any other - name must be defined by creating a PriorityClass object with that name. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessGates: - description: |- - If specified, all readiness gates will be evaluated for pod readiness. - A pod is ready when all its containers are ready AND - all conditions specified in the readiness gates have status equal to "True" - More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - items: - description: PodReadinessGate contains the reference to a pod - condition - properties: - conditionType: - description: ConditionType refers to a condition in the - pod's condition list with matching type. - type: string - required: - - conditionType - type: object - type: array - replicas: - description: Replicas define the number of pods to start by default - for this deployment model. Ignored in "knative" deployment model. - format: int32 - type: integer - resourceClaims: - description: |- - ResourceClaims defines which ResourceClaims must be allocated - and reserved before the Pod is allowed to start. The resources - will be made available to those containers which consume them - by name. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. - items: - description: |- - PodResourceClaim references exactly one ResourceClaim, either directly - or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim - for the pod. - - It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. - Containers that need access to the ResourceClaim reference it with this name. - properties: - name: - description: |- - Name uniquely identifies this resource claim inside the pod. - This must be a DNS_LABEL. - type: string - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. - - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. - - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - - Exactly one of ResourceClaimName and ResourceClaimTemplateName must - be set. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restartPolicy: - description: |- - Restart policy for all containers within the pod. - One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - Default to Always. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - type: string - runtimeClassName: - description: |- - RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - empty definition that uses the default runtime handler. - More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - type: string - schedulerName: - description: |- - If specified, the pod will be dispatched by specified scheduler. - If not specified, the pod will be dispatched by default scheduler. - type: string - schedulingGates: - description: |- - SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - scheduler will not attempt to schedule the pod. - - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. - items: - description: PodSchedulingGate is associated to a Pod to guard - its scheduling. - properties: - name: - description: |- - Name of the scheduling gate. - Each scheduling gate must have a unique name field. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - description: |- - SecurityContext holds pod-level security attributes and common container settings. - Optional: Defaults to empty. See type description for default values of each field. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the - GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the ServiceAccount to use to run this pod. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - setHostnameAsFQDN: - description: |- - If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - If a pod does not have FQDN, this has no effect. - Default to false. - type: boolean - shareProcessNamespace: - description: |- - Share a single process namespace between all of the containers in a pod. - When this is set containers will be able to view and signal processes from other containers - in the same pod, and the first process in each container will not be assigned PID 1. - HostPID and ShareProcessNamespace cannot both be set. - Optional: Default to false. - type: boolean - subdomain: - description: |- - If specified, the fully qualified Pod hostname will be "...svc.". - If not specified, the pod will not have a domainname at all. - type: string - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - If this value is nil, the default grace period will be used instead. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - Defaults to 30 seconds. - format: int64 - type: integer - tolerations: - description: If specified, the pod's tolerations. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of pods ought to spread across topology - domains. Scheduler will schedule pods in a way which abides by the constraints. - All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: |- - List of volumes that can be mounted by containers belonging to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes - items: - description: Volume represents a named volume in a pod that - may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data Disk mount - on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching mode: - None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data disk in - the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk in the - blob storage - type: string - fsType: - default: ext4 - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: multiple - blob disks per storage account Dedicated: single - blob disk per storage account Managed: azure managed - data disk (only in managed availability set). defaults - to shared' - type: string - readOnly: - default: false - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File Service - mount on the host and bind mount to the pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret that - contains Azure Storage Account Name and Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - description: 'path is Optional: Used as the mounted - root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that should - populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API about the - pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API volume - file - items: - description: DownwardAPIVolumeFile represents information - to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the - pod: only annotations, labels, name, namespace - and uid are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. Must not - be absolute or contain the ''..'' path. Must - be utf-8 encoded. The first item of the relative - path must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - 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 - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - 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 - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query over - volumes to consider for binding. - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource that - is attached to a kubelet's host machine and then exposed - to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - lun: - description: 'lun is Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target worldwide - names (WWNs)' - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver to use - for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field holds - extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume attached - to a kubelet's host machine. This depends on the Flocker - control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the dataset. - This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for the specified - revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - image: - description: |- - image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. - The volume is resolved at pod startup depending on which PullPolicy value is provided: - - - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - - The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. - A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. - The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. - The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). - The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. - properties: - pullPolicy: - description: |- - Policy for pulling OCI objects. Possible values are: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - type: string - reference: - description: |- - Required: Image or artifact reference to be used. - Behaves in the same way as pod.spec.containers[*].image. - Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether support - iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether support - iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified Name. - type: string - iscsiInterface: - default: default - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - x-kubernetes-list-type: atomic - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for iSCSI - target and initiator authentication - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets host - machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies Photon Controller - persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a Portworx - volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources secrets, - configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: |- - sources is the list of volume projections. Each entry in this list - handles one source. - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". - 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - x-kubernetes-map-type: atomic - name: - description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. - type: string - optional: - description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the volume - root to write the bundle. - type: string - signerName: - description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. - type: string - required: - - path - type: object - configMap: - description: configMap information about the configMap - data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path - within a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the - ConfigMap or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the - downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name, namespace and uid are supported.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the - relative path name of the file to - be created. Must not be absolute or - contain the ''..'' path. Must be utf-8 - encoded. The first item of the relative - path must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env - vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - secret: - description: secret information about the secret - data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path - within a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify whether - the Secret or its key must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - quobyte: - description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references an already - created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - default: /etc/ceph/keyring - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - default: rbd - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - user: - default: admin - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - default: xfs - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of the ScaleIO - API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the ScaleIO - Protection Domain for the configured storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL communication - with Gateway, default false - type: boolean - storageMode: - default: ThinProvisioned - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage Pool - associated with the protection domain. - type: string - system: - description: system is the name of the storage system - as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether the Secret - or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume attached - and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy Based - Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage Policy - Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - resources: - description: |- - Resources workflow resources that are linked to this workflow definition. - For example, a collection of OpenAPI specification files. - properties: - configMaps: - items: - description: |- - ConfigMapWorkflowResource ConfigMap local reference holding one or more workflow resources, such as OpenAPI files - that will be mounted in the workflow application. - properties: - configMap: - description: ConfigMap the given configMap name in the same - workflow context to find the resource - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - workflowPath: - description: |- - WorkflowPath path relative to the workflow application root file system within the pod (//src/main/resources). - Starting trailing slashes will be removed. - type: string - required: - - configMap - type: object - type: array - type: object - sink: - description: Sink describes the sinkBinding details of this SonataFlow - instance. - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme and non-empty - host) pointing to the target or a relative URI. Relative URIs - will be resolved using the base URI retrieved from Ref. - type: string - type: object - sources: - description: Sources describes the list of sources used to create - triggers for events consumed by this SonataFlow instance. - items: - description: SonataFlowSourceSpec defines the desired state of a - source used for trigger creation - properties: - CACerts: - description: |- - CACerts are Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - If set, these CAs are appended to the set of CAs provided - by the Addressable target, if any. - type: string - audience: - description: |- - Audience is the OIDC audience. - This need only be set, if the target is not an Addressable - and thus the Audience can't be received from the Addressable itself. - In case the Addressable specifies an Audience too, the Destinations - Audience takes preference. - type: string - eventType: - description: Defines the eventType to filter the events - type: string - ref: - description: Ref points to an Addressable. - properties: - address: - description: Address points to a specific Address Name. - type: string - apiVersion: - description: API version of the referent. - type: string - group: - description: |- - Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup. - Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086 - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - This is optional field, it gets defaulted to the object holding it if left out. - type: string - required: - - kind - - name - type: object - uri: - description: URI can be an absolute URL(non-empty scheme and - non-empty host) pointing to the target or a relative URI. - Relative URIs will be resolved using the base URI retrieved - from Ref. - type: string - required: - - eventType - type: object - type: array - required: - - flow - type: object - status: - description: SonataFlowStatus defines the observed state of SonataFlow - properties: - address: - description: Address is used as a part of Addressable interface (status.address.url) - for knative - properties: - CACerts: - description: |- - CACerts is the Certification Authority (CA) certificates in PEM format - according to https://www.rfc-editor.org/rfc/rfc7468. - type: string - audience: - description: Audience is the OIDC audience for this address. - type: string - name: - description: Name is the name of the address. - type: string - url: - type: string - type: object - conditions: - description: The latest available observations of a resource's current - state. - items: - description: Condition describes the common structure for conditions - in our types - properties: - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human-readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type condition for the given object - type: string - required: - - status - - type - type: object - type: array - endpoint: - description: Endpoint is an externally accessible URL of the workflow - type: string - finalizerAttempts: - type: integer - finalizerSucceed: - type: boolean - flowCRC: - format: int32 - type: integer - lastTimeFinalizerAttempt: - format: date-time - type: string - lastTimeRecoverAttempt: - format: date-time - type: string - lastTimeStatusNotified: - format: date-time - type: string - observedGeneration: - description: The generation observed by the deployment controller. - format: int64 - type: integer - platform: - description: Platform displays which platform is being used by this - workflow - properties: - name: - description: Name of the SonataFlowPlatform - type: string - namespace: - description: Namespace of the SonataFlowPlatform - type: string - required: - - name - - namespace - type: object - recoverFailureAttempts: - description: keeps track of how many failure recovers a given workflow - had so far - type: integer - replicas: - description: |- - Replicas is the actual number of observed queryable pods. - This is required by the HPA via the scale subresource. - format: int32 - type: integer - selector: - description: |- - Selector is the queryable label selector for pods, in string format. - HPA uses this to find the pods and collect metrics (CPU/Memory). - type: string - services: - description: Services displays which platform services are being used - by this workflow - properties: - dataIndexRef: - description: DataIndexRef displays information on the cluster-wide - Data Index service - properties: - url: - description: Url displays the base url of the service - type: string - type: object - jobServiceRef: - description: JobServiceRef displays information on the cluster-wide - Job Service - properties: - url: - description: Url displays the base url of the service - type: string - type: object - type: object - triggers: - description: Triggers list of triggers created for the SonataFlow - items: - description: SonataFlowTriggerRef defines a trigger created for - the SonataFlow. - properties: - name: - description: Name of the Trigger - type: string - namespace: - description: Namespace of the Trigger - type: string - required: - - name - - namespace - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.selector - specReplicasPath: .spec.podTemplate.replicas - statusReplicasPath: .status.replicas - status: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-leader-election-role - namespace: sonataflow-operator-system -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-builder-manager-role -rules: -- apiGroups: - - "" - resources: - - configmaps - - pods - - pods/exec - - services - - services/finalizers - - namespaces - - serviceaccounts - - persistentvolumeclaims - - secrets - - events - - deployments - - nodes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - apps - resources: - - configmaps - - pods - - pods/exec - - services - - services/finalizers - - namespaces - - serviceaccounts - - persistentvolumeclaims - - secrets - - events - - deployments - - nodes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - rolebindings - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-knative-manager-role -rules: -- apiGroups: - - eventing.knative.dev - resources: - - triggers - - triggers/status - - triggers/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - sources.knative.dev - resources: - - sinkbindings - - sinkbindings/status - - sinkbindings/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - serving.knative.dev - resources: - - service - - services - - services/status - - services/finalizers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-leases -rules: -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-manager-role -rules: -- apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - verbs: - - get - - list - - watch -- apiGroups: - - batch - resources: - - jobs - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - create - - delete - - get - - list - - update - - watch -- apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - serving.knative.dev - resources: - - revisions - verbs: - - delete - - list - - watch -- apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds - - sonataflowclusterplatforms - - sonataflowplatforms - - sonataflows - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds/finalizers - - sonataflowclusterplatforms/finalizers - - sonataflowplatforms/finalizers - - sonataflows/finalizers - verbs: - - update -- apiGroups: - - sonataflow.org - resources: - - sonataflowbuilds/status - - sonataflowclusterplatforms/status - - sonataflowplatforms/status - - sonataflows/scale - - sonataflows/status - verbs: - - get - - patch - - update ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-metrics-reader -rules: -- nonResourceURLs: - - /metrics - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-openshift-manager-role -rules: -- apiGroups: - - route.openshift.io - resources: - - route - - routes - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - route.openshift.io - resources: - - route/finalizers - - routes/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch -- apiGroups: - - image.openshift.io - resources: - - imagestreams - - imagestreamtags - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - image.openshift.io - resources: - - imagestreams/finalizers - - imagestreamtags/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch -- apiGroups: - - build.openshift.io - resources: - - buildconfigs - - builds - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - build.openshift.io - resources: - - buildconfigs/finalizers - - builds/finalizers - verbs: - - get - - list - - create - - update - - delete - - deletecollection - - patch - - watch -- apiGroups: - - build.openshift.io - resources: - - buildconfigs/instantiatebinary - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-proxy-role -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-service-discovery-role -rules: -- apiGroups: - - apps - resources: - - statefulset - - statefulsets - verbs: - - get - - list - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingress - - ingresses - verbs: - - get - - list - - watch -- apiGroups: - - serving.knative.dev - resources: - - service - - services - verbs: - - get - - list - - watch -- apiGroups: - - eventing.knative.dev - resources: - - broker - - brokers - verbs: - - get - - list - - watch -- apiGroups: - - apps.openshift.io - resources: - - deploymentconfigs - verbs: - - get - - list - - watch -- apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-leader-election-rolebinding - namespace: sonataflow-operator-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: sonataflow-operator-leader-election-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-builder-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-builder-manager-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-knative-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-knative-manager-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-leases-binding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-leases -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-manager-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-openshift-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-openshift-manager-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-proxy-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-service-discovery-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: sonataflow-operator-service-discovery-role -subjects: -- kind: ServiceAccount - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system ---- -apiVersion: v1 -data: - DEFAULT_WORKFLOW_EXTENSION: .sw.json - Dockerfile: "# Licensed to the Apache Software Foundation (ASF) under one\n# or - more contributor license agreements. See the NOTICE file\n# distributed with - this work for additional information\n# regarding copyright ownership. The ASF - licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); - you may not use this file except in compliance\n# with the License. You may obtain - a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# - Unless required by applicable law or agreed to in writing,\n# software distributed - under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES - OR CONDITIONS OF ANY\n# KIND, either express or implied. See the License for - the\n# specific language governing permissions and limitations\n# under the License.\n\nFROM - docker.io/apache/incubator-kie-sonataflow-builder:main AS builder\n\n# variables - that can be overridden by the builder\n# To add a Quarkus extension to your application\nARG - QUARKUS_EXTENSIONS\n# Args to pass to the Quarkus CLI add extension command\nARG - QUARKUS_ADD_EXTENSION_ARGS\n# Additional java/mvn arguments to pass to the builder\nARG - MAVEN_ARGS_APPEND\n\n# Copy from build context to skeleton resources project\nCOPY - --chown=1001 . ./resources\n\nRUN /home/kogito/launch/build-app.sh ./resources\n - \ \n#=============================\n# Runtime Run\n#=============================\nFROM - registry.access.redhat.com/ubi9/openjdk-17-runtime:latest\n\nENV LANG='en_US.UTF-8' - LANGUAGE='en_US:en'\n \n# We make four distinct layers so if there are application - changes the library layers can be re-used\nCOPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/lib/ - /deployments/lib/\nCOPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/*.jar - /deployments/\nCOPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/app/ - /deployments/app/\nCOPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/quarkus/ - /deployments/quarkus/\n\nEXPOSE 8080\nUSER 185\nENV AB_JOLOKIA_OFF=\"\"\nENV JAVA_OPTS=\"-Dquarkus.http.host=0.0.0.0 - -Djava.util.logging.manager=org.jboss.logmanager.LogManager\"\nENV JAVA_APP_JAR=\"/deployments/quarkus-run.jar\"\n" -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-builder-config - namespace: sonataflow-operator-system ---- -apiVersion: v1 -data: - controllers_cfg.yaml: | - # Licensed to the Apache Software Foundation (ASF) under one - # or more contributor license agreements. See the NOTICE file - # distributed with this work for additional information - # regarding copyright ownership. The ASF licenses this file - # to you under the Apache License, Version 2.0 (the - # "License"); you may not use this file except in compliance - # with the License. You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, - # software distributed under the License is distributed on an - # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - # KIND, either express or implied. See the License for the - # specific language governing permissions and limitations - # under the License. - - # The default size of Kaniko PVC when using the internal operator builder manager - defaultPvcKanikoSize: 1Gi - # How much time (in seconds) to wait for a devmode workflow to start. - # This information is used for the controller manager to create new devmode containers and setup the healthcheck probes. - healthFailureThresholdDevMode: 50 - # Default image used internally by the Operator Managed Kaniko builder to create the warmup pods - kanikoDefaultWarmerImageTag: gcr.io/kaniko-project/warmer:v1.9.0 - # Default image used internally by the Operator Managed Kaniko builder to create the executor pods - kanikoExecutorImageTag: gcr.io/kaniko-project/executor:v1.9.0 - # The Jobs Service image to use, if empty the operator will use the default Apache Community one based on the current operator's version - jobsServicePostgreSQLImageTag: "" - jobsServiceEphemeralImageTag: "" - # The Data Index image to use, if empty the operator will use the default Apache Community one based on the current operator's version - dataIndexPostgreSQLImageTag: "" - dataIndexEphemeralImageTag: "" - # The Kogito PostgreSQL DB Migrator image to use - dbMigratorToolImageTag: "" - # SonataFlow base builder image used in the internal Dockerfile to build workflow applications in preview profile - # Order of precedence is: - # 1. SonataFlowPlatform in the given namespace - # 2. This configuration - # 3. The FROM in the Dockerfile in the operator's namespace "sonataflow-operator-builder-config" configMap. - # If 1 or 2, the FROM tag will be replaced by the tag there. - # If empty the operator will use the default Apache Community one based on the current operator's version. - sonataFlowBaseBuilderImageTag: "" - # The image to use to deploy SonataFlow workflow images in devmode profile. - # If empty the operator will use the default Apache Community one based on the current operator's version. - sonataFlowDevModeImageTag: "" - # The default name of the builder configMap in the operator's namespace - builderConfigMapName: "sonataflow-operator-builder-config" - # Quarkus extensions required for workflows persistence. These extensions are used by the SonataFlow build system, - # in cases where the workflow being built has configured postgresql persistence. - postgreSQLPersistenceExtensions: - - groupId: io.quarkus - artifactId: quarkus-jdbc-postgresql - - groupId: io.quarkus - artifactId: quarkus-agroal - - groupId: org.kie - artifactId: kie-addons-quarkus-persistence-jdbc - # If true, the workflow deployments will be configured to send accumulated workflow status change events to the Data - # Index Service reducing the number of produced events. Set to false to send individual events. - kogitoEventsGrouping: true - # If true, the accumulated workflow status change events will be sent in binary mode. (reduces the evens size) - kogitoEventsGroupingBinary: true - # If true, the accumulated workflow status change events, when sent in binary mode, will be gzipped at the cost of - # some performance. - kogitoEventsGroupingCompress: false -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-controllers-config - namespace: sonataflow-operator-system ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-controller-manager-metrics-service - namespace: sonataflow-operator-system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https - selector: - app.kubernetes.io/name: sonataflow-operator ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: sonataflow-operator - name: sonataflow-operator-controller-manager - namespace: sonataflow-operator-system -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: sonataflow-operator - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - app.kubernetes.io/name: sonataflow-operator - spec: - containers: - - args: - - --health-probe-bind-address=:8081 - - --metrics-bind-address=127.0.0.1:8080 - - --leader-elect - - --lease-duration=60s - - --renew-deadline=40s - - --retry-period=15s - - --qps=50 - - --burst=100 - - --v=0 - command: - - /usr/local/bin/manager - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: RELATED_IMAGE_JOBS_SERVICE_POSTGRESQL - value: docker.io/apache/incubator-kie-kogito-jobs-service-postgresql:main - - name: RELATED_IMAGE_JOBS_SERVICE_EPHEMERAL - value: docker.io/apache/incubator-kie-kogito-jobs-service-ephemeral:main - - name: RELATED_IMAGE_DATA_INDEX_POSTGRESQL - value: docker.io/apache/incubator-kie-kogito-data-index-postgresql:main - - name: RELATED_IMAGE_DATA_INDEX_EPHEMERAL - value: docker.io/apache/incubator-kie-kogito-data-index-ephemeral:main - - name: RELATED_IMAGE_DB_MIGRATOR_TOOL - value: docker.io/apache/kie-kogito-db-migrator-tool:main - - name: RELATED_IMAGE_BASE_BUILDER - value: docker.io/apache/incubator-kie-sonataflow-builder:main - - name: RELATED_IMAGE_DEVMODE - value: docker.io/apache/incubator-kie-sonataflow-devmode:main - image: quay.io/kiegroup/logic-operator:2.0.0 - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - name: manager - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 500m - memory: 500Mi - requests: - cpu: 100m - memory: 200Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - volumeMounts: - - mountPath: /config/controllers_cfg.yaml - name: controllers-config - subPath: controllers_cfg.yaml - - args: - - --secure-listen-address=0.0.0.0:8443 - - --upstream=http://127.0.0.1:8080/ - - --logtostderr=true - - --v=0 - env: - - name: RELATED_IMAGE_KUBE_RBAC_PROXY - value: quay.io/brancz/kube-rbac-proxy:v0.13.1 - image: quay.io/brancz/kube-rbac-proxy:v0.13.1 - name: kube-rbac-proxy - ports: - - containerPort: 8443 - name: https - protocol: TCP - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - seccompProfile: - type: RuntimeDefault - securityContext: - runAsNonRoot: true - serviceAccountName: sonataflow-operator-controller-manager - terminationGracePeriodSeconds: 10 - volumes: - - configMap: - name: sonataflow-operator-controllers-config - name: controllers-config diff --git a/test/cfg.go b/test/cfg.go deleted file mode 100644 index bb0ba171..00000000 --- a/test/cfg.go +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/kubesmarts/logic-operator/internal/controller/cfg" -) - -// RestoreControllersConfig Utility function to restore the controllers global configuration in situations where -// a particular test must populate it with values form a given file. As part of the given test finalization we can -// invoke this function to restore the global configuration. -func RestoreControllersConfig(t *testing.T) { - _, err := cfg.InitializeControllersCfgAt(getProjectDir() + "/config/manager/controllers_cfg.yaml") - assert.NoError(t, err) -} diff --git a/test/e2e/clusterplatform_test.go b/test/e2e/clusterplatform_test.go deleted file mode 100644 index 966c81db..00000000 --- a/test/e2e/clusterplatform_test.go +++ /dev/null @@ -1,315 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 e2e - -import ( - //nolint:golint - //nolint:revive - - "bytes" - "fmt" - "math/rand" - "os/exec" - "path/filepath" - "time" - - "github.com/kubesmarts/logic-operator/api/metadata" - "github.com/kubesmarts/logic-operator/internal/controller/platform/services" - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/test/utils" - - //nolint:golint - //nolint:revive - . "github.com/onsi/ginkgo/v2" - - //nolint:golint - //nolint:revive - . "github.com/onsi/gomega" -) - -var _ = Describe("Cluster Platform Use Cases :: ", Label("cluster"), Ordered, func() { - - var ( - projectDir string - targetNamespace string - targetNamespace2 string - ) - - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - cmd := exec.Command("kubectl", "create", "namespace", targetNamespace) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - targetNamespace2 = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - cmd = exec.Command("kubectl", "create", "namespace", targetNamespace2) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespacs with no failure - if !CurrentSpecReport().Failed() { - if len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - } - if len(targetNamespace2) > 0 { - cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace2, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - } - } - - // Remove SonataFlowClusterPlatform created in the last run - cmd := exec.Command("kubectl", "delete", "sonataflowclusterplatform", "--all", "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }) - var _ = Context("with supporting services enabled", func() { - DescribeTable("against a platform in a separate namespace", func(testcaseDir string, profile string, persistenceType string, withServices bool) { - By("Deploy the SonataFlowPlatform CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", - test.GetPathFromE2EDirectory("platform", "services", profile, clusterWideEphemeral)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonataFlowPlatform CR in " + targetNamespace + " to be ready") - // wait for platform to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'") - returnedValue, _ := utils.Run(cmd) - println(string(returnedValue)) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("''"))) - - By("Evaluate status of SonataFlowClusterPlatform CR") - cmd = exec.Command("kubectl", "patch", "SonataFlowClusterPlatform", "cluster", "--type", "merge", "-p", `{"spec": {"platformRef": {"namespace": "`+targetNamespace+`"}}}`) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "SonataFlowClusterPlatform", "cluster", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - - if withServices { - By("Deploy SonataFlowPlatform CR with services configured in " + targetNamespace2) - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, - testcaseDir, profile, persistenceType)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready") - // wait for platform to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Not(Equal([]byte("''")))) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("''"))) - - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace2, prebuiltWorkflows.CallBack.Name, prebuiltWorkflows.CallBack.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Waiting for Data Index and Jobs Service URLs") - dataIndexServiceUrl := services.GenerateServiceURL(constants.DefaultHTTPProtocol, targetNamespace2, "sonataflow-platform-"+constants.DataIndexServiceName) - jobServiceUrl := services.GenerateServiceURL(constants.DefaultHTTPProtocol, targetNamespace2, "sonataflow-platform-"+constants.JobServiceName) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, prebuiltWorkflows.CallBack.Name, "-o", "jsonpath='{.status.services.dataIndexRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 3*time.Minute, 5).Should(Equal([]byte("'" + dataIndexServiceUrl + "'"))) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, prebuiltWorkflows.CallBack.Name, "-o", "jsonpath='{.status.services.jobServiceRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 3*time.Minute, 5).Should(Equal([]byte("'" + jobServiceUrl + "'"))) - } else { - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, - testcaseDir, profile, persistenceType)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready") - dataIndexServiceUrl := services.GenerateServiceURL(constants.DefaultHTTPProtocol, targetNamespace, "sonataflow-platform-"+constants.DataIndexServiceName) - jobServiceUrl := services.GenerateServiceURL(constants.DefaultHTTPProtocol, targetNamespace, "sonataflow-platform-"+constants.JobServiceName) - // wait for platform to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services.dataIndexRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("'" + dataIndexServiceUrl + "'"))) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services.jobServiceRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("'" + jobServiceUrl + "'"))) - - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace2, prebuiltWorkflows.CallBack.Name, prebuiltWorkflows.CallBack.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Waiting for Data Index and Jobs Service URLs") - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, prebuiltWorkflows.CallBack.Name, "-o", "jsonpath='{.status.services.dataIndexRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 3*time.Minute, 5).Should(Equal([]byte("'" + dataIndexServiceUrl + "'"))) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, prebuiltWorkflows.CallBack.Name, "-o", "jsonpath='{.status.services.jobServiceRef.url}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 3*time.Minute, 5).Should(Equal([]byte("'" + jobServiceUrl + "'"))) - } - cmd = exec.Command("kubectl", "delete", "SonataFlowClusterPlatform", "cluster", "--wait") - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }, - Entry("without services configured", test.GetPathFromE2EDirectory("platform", "noservices"), metadata.GitOpsProfile.String(), ephemeral, false), - Entry("with services configured and platform broker", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile.String(), "ephemeral-with-workflow", true), - Entry("with services configured and no broker", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile.String(), "ephemeral-with-workflow-no-broker", true), - ) - - DescribeTable("against a platform in a separate namespace", func(testcaseDir string, profile string, persistenceType string) { - By("Deploy the SonataFlowPlatform CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", test.GetPathFromE2EDirectory("platform", "services", profile, clusterWideEphemeral)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR in " + targetNamespace + " to be ready") - // wait for platform to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'") - returnedValue, _ := utils.Run(cmd) - println(string(returnedValue)) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("''"))) - - By("Evaluate status of SonataFlowClusterPlatform CR") - cmd = exec.Command("kubectl", "patch", "SonataFlowClusterPlatform", "cluster", "--type", "merge", "-p", `{"spec": {"platformRef": {"namespace": "`+targetNamespace+`"}}}`) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "SonataFlowClusterPlatform", "cluster", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, - testcaseDir, profile, persistenceType)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready") - // wait for platform to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 20*time.Minute, 5).Should(Succeed()) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Not(Equal([]byte("''")))) - EventuallyWithOffset(1, func() []byte { - cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services}'") - returnedValue, _ := utils.Run(cmd) - return returnedValue - }, 20*time.Minute, 5).Should(Equal([]byte("''"))) - - cmd = exec.Command("kubectl", "delete", "SonataFlowClusterPlatform", "cluster", "--wait") - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }, - Entry("with only Data Index configured", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile.String(), ephemeralDataIndex), - Entry("with only Job Service configured", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile.String(), ephemeralJobService), - ) - }) -}) diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 7011736c..fd950c89 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -1,218 +1,89 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 e2e import ( - "context" "fmt" "os" "os/exec" - "strings" "testing" - "time" - - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" -) - -// Run e2e tests using the Ginkgo runner. -func TestE2E(t *testing.T) { - RegisterFailHandler(Fail) - GinkgoWriter.Println("Starting SonataFlow Operator suite") - RunSpecs(t, "SonataFlow Operator e2e suite") -} - -// prebuiltWorkflows global accessor for the prebuilt workflows -var prebuiltWorkflows E2EWorkflows -const ( - // resourcesNamespace is the global namespace used to deploy e2e resources - resourcesNamespace = "e2e-resources" - // waitForBuildTimeout is the time we should wait for the workflows to be deployed - waitForBuildTimeout = 15 * time.Minute - - flowCallbackPersistenceName = "callbackstatetimeouts-persistence" - flowCallbackName = "callbackstatetimeouts" - flowGreetingsName = "greetings" + "github.com/kubesmarts/logic-operator/test/utils" ) -type E2EWorkflowEntry struct { - Name string - Tag string -} - -func (e *E2EWorkflowEntry) String() string { - return fmt.Sprintf("%s: %s", e.Name, e.Tag) -} - -type E2EWorkflows struct { - // CallBackPersistence is the prebuilt workflow to use on every use case that requires persistence - CallBackPersistence E2EWorkflowEntry - // CallBack is the prebuilt workflow to use on every use case that requires events or jobs services integration - CallBack E2EWorkflowEntry - // Greetings is the general usage image to use on any use case that requires a SonataFlow deployment - Greetings E2EWorkflowEntry -} - -func (e *E2EWorkflows) String() string { - return fmt.Sprintf("%s \n %s \n %s", e.CallBack, e.CallBackPersistence, e.Greetings) -} +var ( + // Optional Environment Variables: + // - CERT_MANAGER_INSTALL_SKIP=true: Skips CertManager installation during test setup. + // These variables are useful if CertManager is already installed, avoiding + // re-installation and conflicts. + skipCertManagerInstall = os.Getenv("CERT_MANAGER_INSTALL_SKIP") == "true" + // isCertManagerAlreadyInstalled will be set true when CertManager CRDs be found on the cluster + isCertManagerAlreadyInstalled = false + + // projectImage is the name of the image which will be build and loaded + // with the code source changes to be tested. + projectImage = "example.com/logic-operator:v0.0.1" +) -type DeployedWorkflow struct { - YAMLFile string - ImageTag string +// TestE2E runs the end-to-end (e2e) test suite for the project. These tests execute in an isolated, +// temporary environment to validate project changes with the purposed to be used in CI jobs. +// The default setup requires Kind, builds/loads the Manager Docker image locally, and installs +// CertManager. +func TestE2E(t *testing.T) { + RegisterFailHandler(Fail) + _, _ = fmt.Fprintf(GinkgoWriter, "Starting logic-operator integration test suite\n") + RunSpecs(t, "e2e suite") } var _ = BeforeSuite(func() { - GinkgoWriter.Print("Checking if resources namespace is available\n") - namespaceExists, err := kubectlNamespaceExists(resourcesNamespace) - Expect(err).NotTo(HaveOccurred()) - - // Read PREBUILT_WORKFLOWS env var to control which workflows to build - // Format: comma-separated list of workflow names (e.g., "callbackstatetimeouts,callbackstatetimeouts-persistence") - // Default: build all 3 workflows if not specified - prebuiltWorkflowsEnv := os.Getenv("PREBUILT_WORKFLOWS") - var enabledWorkflows map[string]bool - if prebuiltWorkflowsEnv != "" { - enabledWorkflows = make(map[string]bool) - for _, name := range strings.Split(prebuiltWorkflowsEnv, ",") { - enabledWorkflows[strings.TrimSpace(name)] = true + By("building the manager(Operator) image") + cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage)) + _, err := utils.Run(cmd) + ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the manager(Operator) image") + + // TODO(user): If you want to change the e2e test vendor from Kind, ensure the image is + // built and available before running the tests. Also, remove the following block. + By("loading the manager(Operator) image on Kind") + err = utils.LoadImageToKindClusterWithName(projectImage) + ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the manager(Operator) image into Kind") + + // The tests-e2e are intended to run on a temporary cluster that is created and destroyed for testing. + // To prevent errors when tests run in environments with CertManager already installed, + // we check for its presence before execution. + // Setup CertManager before the suite if not skipped and if not already installed + if !skipCertManagerInstall { + By("checking if cert manager is installed already") + isCertManagerAlreadyInstalled = utils.IsCertManagerCRDsInstalled() + if !isCertManagerAlreadyInstalled { + _, _ = fmt.Fprintf(GinkgoWriter, "Installing CertManager...\n") + Expect(utils.InstallCertManager()).To(Succeed(), "Failed to install CertManager") + } else { + _, _ = fmt.Fprintf(GinkgoWriter, "WARNING: CertManager is already installed. Skipping installation...\n") } - GinkgoWriter.Printf("Building only selected workflows: %s\n", prebuiltWorkflowsEnv) - } else { - GinkgoWriter.Println("Building all workflows (default)") - } - - workflows := make(map[string]*DeployedWorkflow, 3) - // Only add workflows that are enabled (or all if env var not set) - if enabledWorkflows == nil || enabledWorkflows[flowCallbackName] { - workflows[flowCallbackName] = &DeployedWorkflow{YAMLFile: test.GetPathFromE2EDirectory("before-suite", "sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts.yaml")} - } - if enabledWorkflows == nil || enabledWorkflows[flowCallbackPersistenceName] { - workflows[flowCallbackPersistenceName] = &DeployedWorkflow{YAMLFile: test.GetPathFromE2EDirectory("before-suite", "sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts-persistence.yaml")} - } - if enabledWorkflows == nil || enabledWorkflows[flowGreetingsName] { - workflows[flowGreetingsName] = &DeployedWorkflow{YAMLFile: test.GetPathFromE2EDirectory("before-suite", "sonataflow.org_v1alpha08_sonataflow-greetings.yaml")} - } - if !namespaceExists { - GinkgoWriter.Println("Creating the resources namespace") - err = kubectlCreateNamespace(resourcesNamespace) - Expect(err).NotTo(HaveOccurred()) - - GinkgoWriter.Println("Pre-built workflows within the cluster") - err = deployWorkflowsAndWaitForBuild(workflows) - Expect(err).NotTo(HaveOccurred()) - } else { - GinkgoWriter.Println("Fetch pre-built workflows images in the cluster") - err = fetchImageTagsBuiltWorkflows(workflows) - if err != nil { - GinkgoWriter.Println("Failed to fetch pre-built workflows images, try to build them") - err = deployWorkflowsAndWaitForBuild(workflows) - } - Expect(err).NotTo(HaveOccurred()) - } - - // Convert to a simpler structure - if workflow, exists := workflows[flowCallbackName]; exists { - prebuiltWorkflows.CallBack.Tag = workflow.ImageTag - prebuiltWorkflows.CallBack.Name = flowCallbackName - } - if workflow, exists := workflows[flowCallbackPersistenceName]; exists { - prebuiltWorkflows.CallBackPersistence.Tag = workflow.ImageTag - prebuiltWorkflows.CallBackPersistence.Name = flowCallbackPersistenceName - } - if workflow, exists := workflows[flowGreetingsName]; exists { - prebuiltWorkflows.Greetings.Tag = workflow.ImageTag - prebuiltWorkflows.Greetings.Name = flowGreetingsName - } - GinkgoWriter.Println("Images are ready for upcoming tests") - - // Delete the workflows since we already have the images in the internal registry, all gucci - for name := range workflows { - err = kubectlPatchSonataFlowScaleDown(resourcesNamespace, name) - Expect(err).NotTo(HaveOccurred()) } }) -func deployWorkflows(workflows map[string]*DeployedWorkflow) error { - for _, workflow := range workflows { - if err := kubectlApplyFileOnCluster(workflow.YAMLFile, resourcesNamespace); err != nil { - return err - } - } - return nil -} - -func fetchImageTagsBuiltWorkflows(workflows map[string]*DeployedWorkflow) error { - ctx, cancel := context.WithTimeout(context.Background(), waitForBuildTimeout) - defer cancel() - - statusChan := make(chan error, len(workflows)) - for name, workflow := range workflows { - go func(wfName string, wf *DeployedWorkflow) { - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - statusChan <- fmt.Errorf("timeout reached: workflow %s in namespace %s did not reach running state", wfName, resourcesNamespace) - return - case <-ticker.C: - if len(wf.ImageTag) == 0 { - cmd := exec.Command("kubectl", "get", "sonataflowbuild", wfName, "-n", resourcesNamespace, "-o", "jsonpath={.status.imageTag}") - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to check the workflow image tag: %v", err)) - statusChan <- err - } - if len(response) > 0 { - GinkgoWriter.Printf("Got response: %s \n", response) - wf.ImageTag = string(response) - statusChan <- nil - } - } - } - } - }(name, workflow) +var _ = AfterSuite(func() { + // Teardown CertManager after the suite if not skipped and if it was not already installed + if !skipCertManagerInstall && !isCertManagerAlreadyInstalled { + _, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling CertManager...\n") + utils.UninstallCertManager() } - - // Wait for all workflows to be in a running state or for errors to occur - for i := 0; i < len(workflows); i++ { - if err := <-statusChan; err != nil { - return err - } - } - - return nil -} - -func deployWorkflowsAndWaitForBuild(workflows map[string]*DeployedWorkflow) error { - if err := deployWorkflows(workflows); err != nil { - return err - } - if err := fetchImageTagsBuiltWorkflows(workflows); err != nil { - return err - } - return nil -} +}) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go new file mode 100644 index 00000000..f712cc74 --- /dev/null +++ b/test/e2e/e2e_test.go @@ -0,0 +1,329 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 e2e + +import ( + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/kubesmarts/logic-operator/test/utils" +) + +// namespace where the project is deployed in +const namespace = "logic-operator-system" + +// serviceAccountName created for the project +const serviceAccountName = "logic-operator-controller-manager" + +// metricsServiceName is the name of the metrics service of the project +const metricsServiceName = "logic-operator-controller-manager-metrics-service" + +// metricsRoleBindingName is the name of the RBAC that will be created to allow get the metrics data +const metricsRoleBindingName = "logic-operator-metrics-binding" + +var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + + // Before running the tests, set up the environment by creating the namespace, + // enforce the restricted security policy to the namespace, installing CRDs, + // and deploying the controller. + BeforeAll(func() { + By("creating manager namespace") + cmd := exec.Command("kubectl", "create", "ns", namespace) + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to create namespace") + + By("labeling the namespace to enforce the restricted security policy") + cmd = exec.Command("kubectl", "label", "--overwrite", "ns", namespace, + "pod-security.kubernetes.io/enforce=restricted") + _, err = utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to label namespace with restricted policy") + + By("installing CRDs") + cmd = exec.Command("make", "install") + _, err = utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to install CRDs") + + By("deploying the controller-manager") + cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectImage)) + _, err = utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to deploy the controller-manager") + }) + + // After all tests have been executed, clean up by undeploying the controller, uninstalling CRDs, + // and deleting the namespace. + AfterAll(func() { + By("cleaning up the curl pod for metrics") + cmd := exec.Command("kubectl", "delete", "pod", "curl-metrics", "-n", namespace) + _, _ = utils.Run(cmd) + + By("undeploying the controller-manager") + cmd = exec.Command("make", "undeploy") + _, _ = utils.Run(cmd) + + By("uninstalling CRDs") + cmd = exec.Command("make", "uninstall") + _, _ = utils.Run(cmd) + + By("removing manager namespace") + cmd = exec.Command("kubectl", "delete", "ns", namespace) + _, _ = utils.Run(cmd) + }) + + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, "Controller logs:\n %s", controllerLogs) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, "Failed to get Controller logs: %s", err) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, "Kubernetes events:\n%s", eventsOutput) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, "Failed to get Kubernetes events: %s", err) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, "Metrics logs:\n %s", metricsOutput) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, "Failed to get curl-metrics logs: %s", err) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + + SetDefaultEventuallyTimeout(2 * time.Minute) + SetDefaultEventuallyPollingInterval(time.Second) + + Context("Manager", func() { + It("should run successfully", func() { + By("validating that the controller-manager pod is running as expected") + verifyControllerUp := func(g Gomega) { + // Get the name of the controller-manager pod + cmd := exec.Command("kubectl", "get", + "pods", "-l", "control-plane=controller-manager", + "-o", "go-template={{ range .items }}"+ + "{{ if not .metadata.deletionTimestamp }}"+ + "{{ .metadata.name }}"+ + "{{ \"\\n\" }}{{ end }}{{ end }}", + "-n", namespace, + ) + + podOutput, err := utils.Run(cmd) + g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") + podNames := utils.GetNonEmptyLines(podOutput) + g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") + controllerPodName = podNames[0] + g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) + + // Validate the pod's status + cmd = exec.Command("kubectl", "get", + "pods", controllerPodName, "-o", "jsonpath={.status.phase}", + "-n", namespace, + ) + output, err := utils.Run(cmd) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") + } + Eventually(verifyControllerUp).Should(Succeed()) + }) + + It("should ensure the metrics endpoint is serving metrics", func() { + By("creating a ClusterRoleBinding for the service account to allow access to metrics") + cmd := exec.Command("kubectl", "create", "clusterrolebinding", metricsRoleBindingName, + "--clusterrole=logic-operator-metrics-reader", + fmt.Sprintf("--serviceaccount=%s:%s", namespace, serviceAccountName), + ) + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to create ClusterRoleBinding") + + By("validating that the metrics service is available") + cmd = exec.Command("kubectl", "get", "service", metricsServiceName, "-n", namespace) + _, err = utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Metrics service should exist") + + By("getting the service account token") + token, err := serviceAccountToken() + Expect(err).NotTo(HaveOccurred()) + Expect(token).NotTo(BeEmpty()) + + By("waiting for the metrics endpoint to be ready") + verifyMetricsEndpointReady := func(g Gomega) { + cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) + output, err := utils.Run(cmd) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + } + Eventually(verifyMetricsEndpointReady).Should(Succeed()) + + By("verifying that the controller manager is serving the metrics server") + verifyMetricsServerStarted := func(g Gomega) { + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + output, err := utils.Run(cmd) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + "Metrics server not yet started") + } + Eventually(verifyMetricsServerStarted).Should(Succeed()) + + By("creating the curl-metrics pod to access the metrics endpoint") + cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never", + "--namespace", namespace, + "--image=curlimages/curl:latest", + "--overrides", + fmt.Sprintf(`{ + "spec": { + "containers": [{ + "name": "curl", + "image": "curlimages/curl:latest", + "command": ["/bin/sh", "-c"], + "args": ["curl -v -k -H 'Authorization: Bearer %s' https://%s.%s.svc.cluster.local:8443/metrics"], + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": ["ALL"] + }, + "runAsNonRoot": true, + "runAsUser": 1000, + "seccompProfile": { + "type": "RuntimeDefault" + } + } + }], + "serviceAccount": "%s" + } + }`, token, metricsServiceName, namespace, serviceAccountName)) + _, err = utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to create curl-metrics pod") + + By("waiting for the curl-metrics pod to complete.") + verifyCurlUp := func(g Gomega) { + cmd := exec.Command("kubectl", "get", "pods", "curl-metrics", + "-o", "jsonpath={.status.phase}", + "-n", namespace) + output, err := utils.Run(cmd) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") + } + Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) + + By("getting the metrics by checking curl-metrics logs") + metricsOutput := getMetricsOutput() + Expect(metricsOutput).To(ContainSubstring( + "controller_runtime_reconcile_total", + )) + }) + + // +kubebuilder:scaffold:e2e-webhooks-checks + + // TODO: Customize the e2e test suite with scenarios specific to your project. + // Consider applying sample/CR(s) and check their status and/or verifying + // the reconciliation by using the metrics, i.e.: + // metricsOutput := getMetricsOutput() + // Expect(metricsOutput).To(ContainSubstring( + // fmt.Sprintf(`controller_runtime_reconcile_total{controller="%s",result="success"} 1`, + // strings.ToLower(), + // )) + }) +}) + +// serviceAccountToken returns a token for the specified service account in the given namespace. +// It uses the Kubernetes TokenRequest API to generate a token by directly sending a request +// and parsing the resulting token from the API response. +func serviceAccountToken() (string, error) { + const tokenRequestRawString = `{ + "apiVersion": "authentication.k8s.io/v1", + "kind": "TokenRequest" + }` + + // Temporary file to store the token request + secretName := fmt.Sprintf("%s-token-request", serviceAccountName) + tokenRequestFile := filepath.Join("/tmp", secretName) + err := os.WriteFile(tokenRequestFile, []byte(tokenRequestRawString), os.FileMode(0o644)) + if err != nil { + return "", err + } + + var out string + verifyTokenCreation := func(g Gomega) { + // Execute kubectl command to create the token + cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( + "/api/v1/namespaces/%s/serviceaccounts/%s/token", + namespace, + serviceAccountName, + ), "-f", tokenRequestFile) + + output, err := cmd.CombinedOutput() + g.Expect(err).NotTo(HaveOccurred()) + + // Parse the JSON output to extract the token + var token tokenRequest + err = json.Unmarshal(output, &token) + g.Expect(err).NotTo(HaveOccurred()) + + out = token.Status.Token + } + Eventually(verifyTokenCreation).Should(Succeed()) + + return out, err +} + +// getMetricsOutput retrieves and returns the logs from the curl pod used to access the metrics endpoint. +func getMetricsOutput() string { + By("getting the curl-metrics logs") + cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput +} + +// tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, +// containing only the token field that we need to extract. +type tokenRequest struct { + Status struct { + Token string `json:"token"` + } `json:"status"` +} diff --git a/test/e2e/helpers.go b/test/e2e/helpers.go deleted file mode 100644 index 71fcd70b..00000000 --- a/test/e2e/helpers.go +++ /dev/null @@ -1,751 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 e2e - -import ( - "bytes" - "encoding/json" - "fmt" - "net/url" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" - "time" - - "k8s.io/apimachinery/pkg/util/intstr" - - "sigs.k8s.io/yaml" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/test/utils" - - //nolint:golint - //nolint:revive - . "github.com/onsi/ginkgo/v2" - - //nolint:golint - //nolint:revive - . "github.com/onsi/gomega" -) - -type health struct { - Status string `json:"status"` - Checks []check `json:"checks"` -} - -type check struct { - Name string `json:"name"` - Status string `json:"status"` - Data map[string]string `json:"data"` -} - -const ( - ephemeral = "ephemeral" - postgreSQL = "postgreSQL" - clusterWideEphemeral = "cluster-wide-ephemeral" - ephemeralDataIndex = "ephemeral-data-index" - ephemeralJobService = "ephemeral-job-service" -) - -const randomIntRange = 16384 //Set to large number to avoid cluster namespace name collisions - -var ( - upStatus string = "UP" -) - -func kubectlApplyFileOnCluster(file, namespace string) error { - cmd := exec.Command("kubectl", "apply", "-f", file, "-n", namespace) - _, err := utils.Run(cmd) - return err -} - -func kubectlApplyKustomizeOnCluster(dir, namespace string) error { - var manifests []byte - var err error - cmd := exec.Command("kubectl", "kustomize", dir) - manifests, err = utils.Run(cmd) - if err != nil { - return err - } - cmd = exec.Command("kubectl", "apply", "-n", namespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - return err -} - -func kubectlDeleteFileOnCluster(file, namespace string) error { - cmd := exec.Command("kubectl", "delete", "-f", file, "-n", namespace) - _, err := utils.Run(cmd) - return err -} - -func kubectlCreateNamespace(namespace string) error { - cmd := exec.Command("kubectl", "create", "namespace", namespace) - _, err := utils.Run(cmd) - return err -} - -func kubectlNamespaceExists(namespace string) (bool, error) { - cmd := exec.Command("kubectl", "get", "namespace", "-o", fmt.Sprintf(`jsonpath={.items[?(@.metadata.name=="%s")].metadata.name}`, namespace)) - output, err := utils.Run(cmd) - if err != nil { - return false, err - } - return len(output) > 0, nil -} - -func kubectlDeleteNamespace(namespace string) error { - cmd := exec.Command("kubectl", "delete", "namespace", namespace) - _, err := utils.Run(cmd) - return err -} - -func kubectlPatchSonataFlowImageAndRollout(namespace, workflowName, image string) error { - cmd := exec.Command("kubectl", "patch", "sonataflow", workflowName, - "--type", "json", "-n", namespace, - "-p", fmt.Sprintf(`[{"op": "replace", "path": "/spec/podTemplate/container/image", "value": "%s"}, {"op": "replace", "path": "/spec/podTemplate/replicas", "value": 1}]`, image)) - _, err := utils.Run(cmd) - return err -} - -func kubectlPatchSonataFlowScaleDown(namespace, workflowName string) error { - cmd := exec.Command("kubectl", "patch", "sonataflow", workflowName, - "--type", "json", "-n", namespace, - "-p", `[{"op": "replace", "path": "/spec/podTemplate/replicas", "value": 0}]`) - _, err := utils.Run(cmd) - return err -} - -func getHealthFromPod(name, namespace string) (*health, error) { - // iterate over all containers to find the one that responds to the HTTP health endpoint - Expect(name).NotTo(BeEmpty(), "pod name is empty") - cmd := exec.Command("kubectl", "get", "pod", name, "-n", namespace, "-o", `jsonpath={.spec.containers[*].name}`) - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - var errs error - for _, cname := range strings.Split(string(output), " ") { - var h *health - h, err = getHealthStatusInContainer(name, cname, namespace) - if err == nil { - return h, nil - } - errs = fmt.Errorf("%v; %w", err, errs) - } - return nil, errs -} - -func verifyHealthStatusInPod(name string, namespace string) { - // iterate over all containers to find the one that responds to the HTTP health endpoint - Expect(name).NotTo(BeEmpty(), "pod name is empty") - cmd := exec.Command("kubectl", "get", "pod", name, "-n", namespace, "-o", `jsonpath={.spec.containers[*].name}`) - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - var errs error - for _, cname := range strings.Split(string(output), " ") { - var h *health - h, err = getHealthStatusInContainer(name, cname, namespace) - if err == nil { - Expect(h.Status).To(Equal(upStatus)) - return - } - - if len(errs.Error()) > 0 { - errs = fmt.Errorf("%v; %w", err, errs) - } else { - errs = err - } - } - Expect(errs).NotTo(HaveOccurred(), fmt.Sprintf("No container was found that could respond to the health endpoint %v", errs)) - -} - -func getHealthStatusInContainer(podName string, containerName string, ns string) (*health, error) { - h := health{} - cmd := exec.Command("kubectl", "exec", "-t", podName, "-n", ns, "-c", containerName, "--", "curl", "-s", "localhost:8080/q/health") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - // On Apache CI Nodes, does not return valid JSON, hence we match first and last brackets by index and extract it - stringOutput := string(output) - startIndex := strings.Index(stringOutput, "{") - endIndex := strings.LastIndex(stringOutput, "}") - if startIndex == 0 { - stringOutput = stringOutput[startIndex : endIndex+1] - } else { - stringOutput = stringOutput[startIndex-1 : endIndex+1] - } - err = json.Unmarshal([]byte(stringOutput), &h) - if err != nil { - GinkgoWriter.Printf("Failed to parse health JSON from %s/%s: %v\nRaw output: %s\n", ns, podName, err, stringOutput) - return nil, fmt.Errorf("failed to execute curl command against health endpoint in container %s:%v with output %s", containerName, err, output) - } - GinkgoWriter.Printf("Health check %s/%s container %s: status=%s\n", ns, podName, containerName, h.Status) - return &h, nil -} - -func verifyWorkflowIsInRunningState(workflowName string, ns string) bool { - cmd := exec.Command("kubectl", "get", "workflow", workflowName, "-n", ns, "-o", "jsonpath={.status.conditions[?(@.type=='Running')].status}") - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to check if workflow is running: %v", err)) - return false - } - - if len(strings.TrimSpace(string(response))) == 0 { - // Only log debug info occasionally to avoid spam - check the full status - cmd = exec.Command("kubectl", "get", "workflow", workflowName, "-n", ns, "-o", "jsonpath={.status}") - statusOutput, _ := utils.Run(cmd) - if len(statusOutput) == 0 { - GinkgoWriter.Printf("Workflow %s/%s: status not yet set by controller\n", ns, workflowName) - } else { - GinkgoWriter.Printf("Workflow %s/%s: Running condition not found. Status: %s\n", ns, workflowName, string(statusOutput)) - } - return false - } - - status, err := strconv.ParseBool(string(response)) - if err != nil { - GinkgoWriter.Printf("Workflow %s/%s: failed to parse Running condition value '%s': %v\n", ns, workflowName, string(response), err) - return false - } - - if status { - GinkgoWriter.Printf("Workflow %s/%s: Running condition is True\n", ns, workflowName) - } - return status -} - -func verifyWorkflowReplicas(workflowName string, ns string, expectedReplicas int32) bool { - return verifyObjectReplicasFromPath(workflowName, ns, "workflow", "", "jsonpath='{.spec.podTemplate.replicas}'", expectedReplicas) -} - -func verifyWorkflowScaleSubresourceReplicas(workflowName string, ns string, expectedReplicas int32) bool { - return verifyObjectReplicasFromPath(workflowName, ns, "workflow", "--subresource=scale", "jsonpath='{.spec.replicas}'", expectedReplicas) -} - -func verifyWorkflowScaleSubresourceStatusReplicas(workflowName string, ns string, expectedReplicas int32) bool { - return verifyObjectReplicasFromPath(workflowName, ns, "workflow", "--subresource=scale", "jsonpath='{.status.replicas}'", expectedReplicas) -} - -func verifyDeploymentReplicas(name string, ns string, expectedReplicas int32) bool { - return verifyObjectReplicasFromPath(name, ns, "deployment", "", "jsonpath='{.spec.replicas}'", expectedReplicas) -} - -func verifyObjectReplicasFromPath(name string, ns string, objetType string, subResource string, replicasPath string, expectedReplicas int32) bool { - var cmd *exec.Cmd - if len(subResource) > 0 { - cmd = exec.Command("kubectl", "get", objetType, name, "-n", ns, subResource, "-o", replicasPath) - } else { - cmd = exec.Command("kubectl", "get", objetType, name, "-n", ns, "-o", replicasPath) - } - - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Printf("Failed to get %s %s/%s replicas: %v\n", objetType, ns, name, err) - return false - } - replicas, err := extractInt32FromResponse(response) - if err != nil { - GinkgoWriter.Printf("%s %s/%s: failed to parse replicas from '%s': %v\n", objetType, ns, name, string(response), err) - return false - } - if replicas != expectedReplicas { - GinkgoWriter.Printf("%s %s/%s: replicas=%d, waiting for %d\n", objetType, ns, name, replicas, expectedReplicas) - return false - } - GinkgoWriter.Printf("%s %s/%s: replicas=%d (expected)\n", objetType, ns, name, replicas) - return true -} - -func extractInt32FromResponse(response []byte) (int32, error) { - strResponse := strings.ToLower(string(response)) - if strings.Contains(strResponse, "error") || strings.Contains(strResponse, "not found") { - return -1, fmt.Errorf("%s", response) - } - strResponse = extractFromSingleQuotedResponse(strResponse) - replicas, err := strconv.ParseInt(strResponse, 10, 32) - if err != nil { - return -1, err - } - return int32(replicas), nil -} - -func verifyResourceExists(name string, resourceType string, ns string) bool { - cmd := exec.Command("kubectl", "get", resourceType, name, "-n", ns, "-o", "jsonpath='{.metadata.name}'") - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to check if resource exists, name: %s, resourceType: %s, ns: %s, %v", name, resourceType, ns, err)) - return false - } - strResponse := string(response) - if strings.Contains(strResponse, "NotFound") || strings.Contains(strResponse, "not found") { - return false - } - return name == extractFromSingleQuotedResponse(strResponse) -} - -func verifyPodDisruptionBudgetConditionHasStatus(name string, ns string, condition string, status string) bool { - jsonPath := fmt.Sprintf("jsonpath='{.status.conditions[?(@.type==\"%s\")].status}'", condition) - cmd := exec.Command("kubectl", "get", "pdb", name, "-n", ns, "-o", jsonPath) - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get status value for condition: %s from PodDisruptionBudget: %s/%s, %v", condition, ns, name, err)) - return false - } - return status == extractFromSingleQuotedResponse(string(response)) -} - -func verifyPodDisruptionBudgetAllowsDisruptionNumber(name string, ns string, expectedAllowedDisruptions int32) bool { - cmd := exec.Command("kubectl", "get", "pdb", name, "-n", ns, "-o", "jsonpath='{.status.disruptionsAllowed}'") - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get the number of disruptionsAllowed from PodDisruptionBudget: %s/%s, %v", ns, name, err)) - return false - } - allowedDisruptions, err := extractInt32FromResponse(response) - if err != nil { - return false - } - return allowedDisruptions == expectedAllowedDisruptions -} - -func extractFromSingleQuotedResponse(response string) string { - result := strings.TrimSpace(response) - result = strings.TrimPrefix(response, "'") - return strings.TrimSuffix(result, "'") -} - -func createTmpCopy(srcPath string) string { - tmpDir := GinkgoT().TempDir() - fileName := filepath.Base(srcPath) - dstPath := filepath.Join(tmpDir, fileName) - // read source - data, err := os.ReadFile(srcPath) - if err != nil { - GinkgoT().Fatal(err) - } - // write copied file - if err := os.WriteFile(dstPath, data, 0644); err != nil { - GinkgoT().Fatal(err) - } - return dstPath -} - -func setReplicasOrFail(workflowFile string, replicas int32) { - if err := setReplicas(workflowFile, replicas); err != nil { - GinkgoT().Fatal(err) - } -} - -func setImageAndReplicasOrFail(workflowFile, newImage string, replicas int32) { - if err := setImageAndReplicas(workflowFile, newImage, replicas); err != nil { - GinkgoT().Fatal(err) - } -} - -func setPodDisruptionBudgetOrFail(workflowFile string, minAvailable *intstr.IntOrString, maxUnavailable *intstr.IntOrString) { - err := applyWorkflowTransform(workflowFile, func(workflow *operatorapi.SonataFlow) { - if minAvailable == nil && maxUnavailable == nil { - workflow.Spec.PodTemplate.PodDisruptionBudget = nil - } else { - workflow.Spec.PodTemplate.PodDisruptionBudget = &operatorapi.PodDisruptionBudgetSpec{ - MinAvailable: minAvailable, - MaxUnavailable: maxUnavailable, - } - } - }) - if err != nil { - GinkgoT().Fatal(err) - } -} - -func setReplicas(workflowFile string, replicas int32) error { - return applyWorkflowTransform(workflowFile, func(workflow *operatorapi.SonataFlow) { - workflow.Spec.PodTemplate.Replicas = &replicas - }) -} - -func setImageAndReplicas(workflowFile, newImage string, replicas int32) error { - return applyWorkflowTransform(workflowFile, func(workflow *operatorapi.SonataFlow) { - workflow.Spec.PodTemplate.Container.Image = newImage - workflow.Spec.PodTemplate.Replicas = &replicas - }) -} - -func setProfileOrFail(workflowFile, profile string) { - if err := setProfile(workflowFile, profile); err != nil { - GinkgoT().Fatal(err) - } -} - -func setProfile(workflowFile, profile string) error { - return applyWorkflowTransform(workflowFile, func(workflow *operatorapi.SonataFlow) { - workflow.Annotations["sonataflow.org/profile"] = profile - }) -} - -func applyWorkflowTransform(workflowFile string, transform func(flow *operatorapi.SonataFlow)) error { - data, err := os.ReadFile(workflowFile) - if err != nil { - return err - } - - var workflow operatorapi.SonataFlow - if err := yaml.Unmarshal(data, &workflow); err != nil { - return err - } - - transform(&workflow) - - output, err := yaml.Marshal(workflow) - if err != nil { - return err - } - if err := os.WriteFile(workflowFile, output, 0644); err != nil { - return err - } - - return nil -} - -func verifyWorkflowIsAddressable(workflowName string, targetNamespace string) bool { - cmd := exec.Command("kubectl", "get", "workflow", workflowName, "-n", targetNamespace, "-ojsonpath={.status.address.url}") - response, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Printf("Workflow %s/%s: failed to get address: %v\n", targetNamespace, workflowName, err) - return false - } - - if len(strings.TrimSpace(string(response))) == 0 { - GinkgoWriter.Printf("Workflow %s/%s: address.url not yet set\n", targetNamespace, workflowName) - return false - } - - _, err = url.ParseRequestURI(string(response)) - if err != nil { - GinkgoWriter.Printf("Workflow %s/%s: invalid URL '%s': %v\n", targetNamespace, workflowName, string(response), err) - return false - } - - GinkgoWriter.Printf("Workflow %s/%s: addressable at %s\n", targetNamespace, workflowName, string(response)) - return true -} - -func verifySchemaMigration(data, name string) bool { - matched1, err := regexp.MatchString(fmt.Sprintf("Successfully applied \\d migrations to schema \"%s\"", name), data) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("string match error:%v", err)) - return false - } - matched2, err := regexp.MatchString("Successfully validated \\d (migration|migrations)", data) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("string match error:%v", err)) - return false - } - GinkgoWriter.Println(fmt.Sprintf("verifying schemaMigration, logs=%v", data)) - return (matched1 && strings.Contains(data, fmt.Sprintf("Creating schema \"%s\"", name)) && - strings.Contains(data, fmt.Sprintf("Migrating schema \"%s\" to version", name))) || - (matched2 && strings.Contains(data, fmt.Sprintf("Current version of schema \"%s\"", name)) && - strings.Contains(data, fmt.Sprintf("Schema \"%s\" is up to date. No migration necessary", name))) || - (strings.Contains(data, fmt.Sprintf("Creating schema \"%s\"", name)) && - strings.Contains(data, fmt.Sprintf("Current version of schema \"%s\"", name)) && - strings.Contains(data, fmt.Sprintf("Schema \"%s\" is up to date. No migration necessary", name))) -} - -func verifyKSinkInjection(label, ns string) bool { - cmd := exec.Command("kubectl", "get", "pod", "-n", ns, "-l", label, "-o", "jsonpath={.items[*].metadata.name}") - out, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get pods: %v", err)) - return false - } - podNames := strings.Fields(string(out)) - if len(podNames) == 0 { - GinkgoWriter.Println("no pods found to check K_SINK") - return false // pods haven't created yet - } - GinkgoWriter.Println(fmt.Sprintf("pods found: %s", podNames)) - for _, pod := range podNames { - cmd = exec.Command("kubectl", "get", "pod", pod, "-n", ns, "-o", "json") - out, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get pod: %v", err)) - return false - } - GinkgoWriter.Println(string(out)) - if !strings.Contains(string(out), "K_SINK") { // The pod does not have K_SINK injected - GinkgoWriter.Println(fmt.Sprintf("Pod does not have K_SINK injected: %s", string(out))) - return false - } - } - return true -} - -func waitForPodRestartCompletion(label, ns string) (podRunning string) { - EventuallyWithOffset(1, func() bool { - cmd := exec.Command("kubectl", "get", "pod", "-n", ns, "-l", label, "-o", "jsonpath={.items[*].metadata.name}") - out, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get pods: %v", err)) - return false - } - podNames := strings.Fields(string(out)) - if len(podNames) == 0 { - GinkgoWriter.Println("no pods found") - return false // pods haven't created yet - } else if len(podNames) > 1 { - GinkgoWriter.Println("multiple pods found") - return false // multiple pods found, wait for other pods to terminate - } - podRunning = podNames[0] - return true - }, 10*time.Minute, 5).Should(BeTrue()) - - return -} - -func verifyTrigger(triggers []operatorapi.SonataFlowPlatformTriggerRef, namePrefix, path, ns, broker string) error { - GinkgoWriter.Println("Triggers from platform status:", triggers) - for _, ref := range triggers { - if strings.HasPrefix(ref.Name, namePrefix) && ref.Namespace == ns { - EventuallyWithOffset(1, func() error { - return verifyTriggerData(ref.Name, ns, path, broker) - }, 2*time.Minute, 5).Should(Succeed()) - return nil - } - } - return fmt.Errorf("failed to find trigger to verify with prefix: %v, namespace: %v", namePrefix, ns) -} - -func verifyTriggerData(name, ns, path, broker string) error { - cmd := exec.Command("kubectl", "get", "trigger", name, "-n", ns, "-ojsonpath={.spec.broker} {.status.subscriberUri} {.status.conditions[?(@.type=='Ready')].status}") - out, err := utils.Run(cmd) - if err != nil { - return err - } - data := strings.Fields(string(out)) - if len(data) == 3 && broker == data[0] && strings.HasSuffix(data[1], path) && data[2] == "True" { - return nil - } - return fmt.Errorf("failed to verify trigger %v with namespace %v, path %v, broker %s, and received data=%s", name, ns, path, broker, string(out)) -} - -func verifySinkBinding(name, ns, broker string) error { - cmd := exec.Command("kubectl", "get", "sinkbinding", name, "-n", ns, "-ojsonpath={.status.sinkUri} {.status.conditions[?(@.type=='Ready')].status}") - out, err := utils.Run(cmd) - if err != nil { - return err - } - data := strings.Fields(string(out)) - if len(data) == 2 && strings.HasSuffix(data[0], broker) && data[1] == "True" { - return nil - } - return fmt.Errorf("failed to verify sinkbinding %v, data=%s", name, string(out)) -} - -func getWorkflowId(resp string) (string, error) { - // First find the json data - ind1 := strings.Index(resp, "{") - ind2 := strings.LastIndex(resp, "}") - data := resp[ind1 : ind2+1] - // Retrieve the id from json data - m := make(map[string]interface{}) - err := json.Unmarshal([]byte(data), &m) - if err != nil { - return "", err - } - if id, ok := m["id"].(string); ok { - return id, nil - } - return "", fmt.Errorf("failed to find workflow id") -} - -func getMetricValue(resp string) (string, error) { - fmt.Println(resp) - ind1 := strings.Index(resp, "{") - ind2 := strings.LastIndex(resp, "}") - data := resp[ind1 : ind2+1] - - // Retrieve the metric value from json data - m := make(map[string]interface{}) - err := json.Unmarshal([]byte(data), &m) - if err != nil { - return "", err - } - result, ok := m["data"].(map[string]interface{})["result"] - if !ok { - return "", fmt.Errorf("no valid response data received") - } - metrics := result.([]interface{}) - if len(metrics) == 0 { - return "", fmt.Errorf("no valid metric data retrieved") - } - metric := metrics[0] - values := metric.(map[string]interface{})["value"] - if val, ok := (values.([]interface{}))[1].(string); ok { - return val, nil - } else { - return "", fmt.Errorf("failed to get metric value") - } -} - -func getPodNameAfterWorkflowInstCreation(name, ns string) (string, error) { - labels := fmt.Sprintf("sonataflow.org/workflow-app=%s,sonataflow.org/workflow-namespace=%s", name, ns) - cmd := exec.Command("kubectl", "get", "pod", "-n", ns, "-l", labels, "-o=jsonpath='{range .items[*]}{.metadata.name} {.status.conditions[?(@.type=='Ready')].status}{';'}{end}'") - fmt.Println(cmd.String()) - out, err := utils.Run(cmd) - if err != nil { - return "", err - } - fmt.Println(string(out)) - data := strings.Split(string(out), ";") - for _, line := range data { - res := strings.Fields(line) - if len(res) == 2 && strings.Contains(res[0], "-00002-deployment-") { - if res[1] == "True" { - return res[0], nil - } else { - return "", fmt.Errorf("pod %s is not ready=", res) - } - } - } - return "", fmt.Errorf("invalid data received: %s", string(out)) -} - -// extractJSONResponse utility function to extract the json portion of the output produced when we execute commands -// inside a pod via kubectl exec podname xxxx. On the basis of course that the given command execution produces a json. -// Below we show an example of the full output returned by the kubectl exec podname xxxx command execution, however we -// are only interested on the json part: {"data":{"ProcessDefinitions":[]}} -// -// % Total % Received % Xferd Average Speed Time Time Time Current -// Dload Upload Total Spent Left Speed -// -// 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0{"data":{"ProcessDefinitions":[]}} -// 100 85 100 34 100 51 8500 12750 --:--:-- --:--:-- --:--:-- 21250 -func extractJSONResponse(terminalOutput string) string { - ind1 := strings.Index(terminalOutput, "{") - ind2 := strings.LastIndex(terminalOutput, "}") - return terminalOutput[ind1 : ind2+1] -} - -// verifyWorkflowDefinitionIsInStatus returns true if the workflow definition has the status == expectedStatus in the -// target data-index, false in any other case. -func verifyWorkflowDefinitionIsInStatus(podName string, containerName string, namespace, dataIndexServiceName string, workflowId string, expectedStatus string) bool { - status, ok, err := getWorkflowDefinitionStatus(podName, containerName, namespace, dataIndexServiceName, workflowId) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to verify workflow definition status for workflow: %s : %v", workflowId, err)) - } - return ok && status == expectedStatus -} - -// getWorkflowDefinitionStatus returns the "status" of a workflow definition, true if the workflow definition was found -// for that workflowId, false if not found. Returned value is read as follows: -// true, "" : the "status" was not set in the workflow definition metadata. (not yet populated) -// true, "available" : workflow definition is available. -// true, "unavailable" : workflow definition is not available. -// false, "" : workflow definition was not found. -func getWorkflowDefinitionStatus(podName string, containerName string, namespace string, dataIndexServiceName string, workflowId string) (string, bool, error) { - - // DI query example like executed in bash terminal: {"query" : "{ ProcessDefinitions ( where:{id: {equal: \"greet\"}} ) { metadata } }" } - // WF not found query result example: {"data":{"ProcessDefinitions":[]}} - // WF found query result example: {"data":{"ProcessDefinitions":[{"metadata":{"status":"available","Variable":"workflowdata","Description":"YAML based greeting workflow"}}]}} - - query := fmt.Sprintf("{\"query\" : \"{ ProcessDefinitions (where:{id: {equal: \\\"%s\\\"}} ) { metadata } }\" }", workflowId) - curlCmd := fmt.Sprintf("curl -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST --data '%s' http://%s/graphql", query, dataIndexServiceName) - fmt.Printf("querying workflow definition metadata for workflowId: %s, curl: %s\n", workflowId, curlCmd) - - // execute with bash command to ensure the json response is not clipped from the terminal output - cmd := exec.Command("kubectl", "exec", podName, "-c", containerName, "-n", namespace, "--", "/bin/bash", "-c", curlCmd) - output, err := utils.Run(cmd) - if err != nil { - return "", false, fmt.Errorf("failed to execute query against data-index service: %s, from pod: %s, containter: %s, output: %s, error: %v", dataIndexServiceName, podName, containerName, output, err) - } - stringOutput := string(output) - jsonOutput := extractJSONResponse(stringOutput) - fmt.Printf("query result: %s\n", jsonOutput) - - queryResult := make(map[string]interface{}) - err = json.Unmarshal([]byte(jsonOutput), &queryResult) - if err != nil { - return "", false, fmt.Errorf("failed to parse data-index query result from query against data-index service: %s, from pod: %s, container: %s, queryResult: %s, error: %v", dataIndexServiceName, podName, containerName, queryResult, err) - } - rawData, ok := queryResult["data"] - if !ok { - // the "data" field must be present, if not, an error was produced in the DI, e.g., the query was formulated wrong. - return "", false, fmt.Errorf("failed to execute data-index query against data-index service: %s, from pod: %s, container: %s. It looks like the query was formulated wrong, query: %s, queryResult: %s", dataIndexServiceName, podName, containerName, query, queryResult) - } - data := rawData.(map[string]interface{}) - definitions := data["ProcessDefinitions"].([]interface{}) - if len(definitions) == 0 { - // workflow definition not found - return "", false, nil - } - definition := definitions[0].(map[string]interface{}) - rawMetadata, ok := definition["metadata"] - if !ok { - return "", false, nil - } - metadata := rawMetadata.(map[string]interface{}) - available, ok := metadata["status"] - if !ok { - return "", false, nil - } - return available.(string), true, nil -} - -// patchSFPDataIndexReplicas executes a patch command for the dataIndex replicas in the given platform. -func patchSFPDataIndexReplicas(sfpName string, ns string, replicas string) error { - return patchSFPServiceReplicas(sfpName, ns, "dataIndex", replicas) -} - -// patchSFPDataIndexReplicas executes a patch command for the jobService replicas in the given platform. -func patchSFPJobServiceReplicas(sfpName string, ns string, replicas string) error { - return patchSFPServiceReplicas(sfpName, ns, "jobService", replicas) -} - -// patchSFPServiceReplicas use any of the patchSFPDataIndexReplicas or patchSFPJobServiceReplicas variants. -func patchSFPServiceReplicas(sfpName string, ns string, serviceField string, replicas string) error { - patch := fmt.Sprintf(`{"spec":{"services":{"%s":{"podTemplate":{"replicas":%s}}}}}`, serviceField, replicas) - cmd := exec.Command("kubectl", "patch", "sonataflowplatform", sfpName, "-n", ns, "--type=merge", "-p", patch) - response, err := utils.Run(cmd) - if err != nil { - return fmt.Errorf("failed to patch the replicas the service: %s in SonataFlowPlatform %s/%s, %v", serviceField, ns, sfpName, err) - } - strResponse := extractFromSingleQuotedResponse(string(response)) - if !strings.HasPrefix(strResponse, fmt.Sprintf("sonataflowplatform.sonataflow.org/%s patched", sfpName)) { - return fmt.Errorf("failed to patch the replicas for the service: %s in SonataFlowPlatform %s/%s, verify that the platform exists in the namespace: %s, %v", serviceField, ns, sfpName, ns, strResponse) - } - return nil -} - -// patchHPAMinReplicas executes a patch command for the HorizontalPodAutoscaler minReplicas. -func patchHPAMinReplicas(name string, ns string, replicas string) error { - patch := fmt.Sprintf(`{"spec":{"minReplicas":%s}}`, replicas) - cmd := exec.Command("kubectl", "patch", "horizontalpodautoscaler", name, "-n", ns, "--type=merge", "-p", patch) - response, err := utils.Run(cmd) - if err != nil { - return fmt.Errorf("failed to patch the minReplicas for the HPA: %s/%s, %v", ns, name, err) - } - strResponse := extractFromSingleQuotedResponse(string(response)) - if !strings.HasPrefix(strResponse, fmt.Sprintf("horizontalpodautoscaler.autoscaling/%s patched", name)) { - return fmt.Errorf("failed to patch the minReplicas for the HPA %s/%s, verify that the HPA exists in the namespace: %s, %s", ns, name, ns, strResponse) - } - return nil -} diff --git a/test/e2e/platform_test.go b/test/e2e/platform_test.go deleted file mode 100644 index 240a3786..00000000 --- a/test/e2e/platform_test.go +++ /dev/null @@ -1,691 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 e2e - -import ( - "bytes" - "encoding/json" - "fmt" - "math/rand" - "os/exec" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - "github.com/kubesmarts/logic-operator/internal/controller/profiles/common/constants" - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/test/utils" - - //nolint:golint - //nolint:revive - . "github.com/onsi/ginkgo/v2" - - //nolint:golint - //nolint:revive - . "github.com/onsi/gomega" -) - -var _ = Describe("Platform Use Cases :: ", Label("platform"), Ordered, func() { - - var ( - projectDir string - targetNamespace string - targetNamespace2 string - ) - - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - cmd := exec.Command("kubectl", "create", "namespace", targetNamespace) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - targetNamespace2 = fmt.Sprintf("test-%d", rand.Intn(1024)+1) - cmd = exec.Command("kubectl", "create", "namespace", targetNamespace2) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace with no failure - if !CurrentSpecReport().Failed() { - if len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - } - if len(targetNamespace2) > 0 { - cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace2, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - } - } - }) - - var _ = Describe("Db migration :: ", Ordered, func() { - - Describe("ensure service based db migration", func() { - projectDir, _ := utils.GetProjectDir() - It("should successfully deploy the SonataFlowPlatform with data index and jobs service", func() { - By("Deploy the CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, - "test/e2e/testdata/platform/persistence/service_based_db_migration")) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 10*time.Minute, 5).Should(Succeed()) - - By("Evaluate status of all service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - }) - }) - - }) - - var _ = Context("with platform services", func() { - - DescribeTable("when creating a simple workflow", func(testcaseDir string, profile metadata.ProfileType, persistenceType string) { - By("Deploy the SonataFlowPlatform CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, - testcaseDir, profile.String(), persistenceType)) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - By("Wait for SonataFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() bool { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - if err != nil { - return false - } - if profile == metadata.GitOpsProfile { - GinkgoWriter.Println("waitForPodRestartCompletion") - waitForPodRestartCompletion("app.kubernetes.io/name=jobs-service", targetNamespace) - GinkgoWriter.Println("waitForPodRestartCompletion done") - return true - } - return true - }, 30*time.Minute, 5).Should(BeTrue()) - By("Evaluate status of service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - // remove the last CR that is added by default as the last character of the string. - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - By("Deploy the SonataFlow CR") - cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", filepath.Join(projectDir, - testcaseDir, profile.String(), persistenceType, "sonataflow")) - manifests, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Retrieve SonataFlow CR name") - cmd = exec.Command("kubectl", "get", "sonataflow", "-n", targetNamespace, `-ojsonpath={.items[*].metadata.name}`) - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - sfNames := strings.TrimRight(string(output), " ") - - if profile == metadata.GitOpsProfile { - workflowTag := prebuiltWorkflows.CallBack.Tag - if persistenceType == postgreSQL { - workflowTag = prebuiltWorkflows.CallBackPersistence.Tag - } - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace, sfNames, workflowTag) - }, 3*time.Minute, time.Second).Should(Succeed()) - } - - By("Evaluate status of SonataFlow CR") - for _, sf := range strings.Split(sfNames, " ") { - Expect(sf).NotTo(BeEmpty(), "sonataflow name is empty") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowIsInRunningState(sf, targetNamespace) - }, 3*time.Minute, 5*time.Second).Should(BeTrue()) - } - - if profile != metadata.DevProfile { - By("Verify that the workflow definition is available") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - dataIndexPod := string(output) - - // Workflow ID varies by persistence type - workflowId := "callbackstatetimeouts" - if persistenceType == postgreSQL { - workflowId = "callbackstatetimeouts-persistence" - } - - EventuallyWithOffset(1, func() bool { - return verifyWorkflowDefinitionIsInStatus(dataIndexPod, "data-index-service", targetNamespace, "sonataflow-platform-data-index-service", workflowId, "available") - }, 3*time.Minute, 5*time.Second).Should(BeTrue()) - - By("Undeploy the SonataFlow CR") - cmd = exec.Command("kubectl", "delete", "-n", targetNamespace, "-f", filepath.Join(projectDir, - testcaseDir, profile.String(), persistenceType, "sonataflow")) - manifests, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Verify that the workflow definition is unavailable") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowDefinitionIsInStatus(dataIndexPod, "data-index-service", targetNamespace, "sonataflow-platform-data-index-service", workflowId, "unavailable") - }, 3*time.Minute, 5*time.Second).Should(BeTrue()) - } - }, - Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a dev profile", test.GetPathFromE2EDirectory("platform", "services"), metadata.DevProfile, ephemeral), - Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a gitops profile", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile, ephemeral), - Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a dev profile", test.GetPathFromE2EDirectory("platform", "services"), metadata.DevProfile, postgreSQL), - Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a gitops profile", test.GetPathFromE2EDirectory("platform", "services"), metadata.GitOpsProfile, postgreSQL), - ) - - }) - - DescribeTable("when deploying a SonataFlowPlatform CR with PostgreSQL Persistence", func(testcaseDir string) { - By("Deploy the CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - By("Wait for SonatatFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 10*time.Minute, 5).Should(Succeed()) - By("Evaluate status of all service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - }, - Entry("and both Job Service and Data Index using the persistence from platform CR", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr")), - Entry("and both Job Service and Data Index using the one defined in each service, discarding the one from the platform CR", test.GetPathFromE2EDirectory("platform", "persistence", "overwritten_by_services")), - Entry("Job Service and Data Index come up with service based db migration", test.GetPathFromE2EDirectory("platform", "persistence", "service_based_db_migration")), - ) - - DescribeTable("when deploying a SonataFlowPlatform CR with PostgreSQL Persistence and using Job based DB migration", func(testcaseDir string) { - By("Deploy the Postgres DB") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir+"/pg-service") - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for Postgres DB to come alive") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (postgres)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 5*time.Minute, 5).Should(Succeed()) - - By("Deploy the CR") - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir+"/sonataflow-platform") - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 10*time.Minute, 5).Should(Succeed()) - - By("Evaluate status of all service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - }, - Entry("Job Service and Data Index come up with job based db migration", test.GetPathFromE2EDirectory("platform", "persistence", "job_based_db_migration")), - ) - - DescribeTable("when deploying a SonataFlowPlatform CR with brokers", func(testcaseDir string) { - By("Deploy the brokers") - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", filepath.Join(projectDir, - testcaseDir, "broker")) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for the brokers to be ready") - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "broker", "-l", "test=test-e2e", "-n", targetNamespace, "--for", "condition=Ready=True", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - By("Deploy the CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - By("Wait for SonatatFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 10*time.Minute, 5).Should(Succeed()) - - GinkgoWriter.Println("waitForPodRestartCompletion") - waitForPodRestartCompletion("app.kubernetes.io/name=jobs-service", targetNamespace) - GinkgoWriter.Println("waitForPodRestartCompletion done") - - By("Evaluate status of all service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - By("Evaluate triggers and sinkbindings") - cmd = exec.Command("kubectl", "get", "sonataflowplatform", "sonataflow-platform", "-n", targetNamespace, "-ojsonpath={.status.triggers}") - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - var triggers []operatorapi.SonataFlowPlatformTriggerRef - err = json.Unmarshal(output, &triggers) - Expect(err).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-error-", constants.KogitoProcessInstancesEventsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-node-", constants.KogitoProcessInstancesEventsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-state-", constants.KogitoProcessInstancesEventsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-variable-", constants.KogitoProcessInstancesEventsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-definition-", constants.KogitoProcessDefinitionsEventsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-jobs-", constants.KogitoJobsPath, targetNamespace, "di-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "jobs-service-create-job-", constants.JobServiceJobEventsPath, targetNamespace, "js-source")).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "jobs-service-delete-job-", constants.JobServiceJobEventsPath, targetNamespace, "js-source")).NotTo(HaveOccurred()) - Expect(verifySinkBinding("sonataflow-platform-jobs-service-sb", targetNamespace, "js-sink")).NotTo(HaveOccurred()) - }, - Entry("and both Job Service and Data Index have service level brokers", test.GetPathFromE2EDirectory("platform", "services", "gitops", "knative", "service-level-broker")), - ) - - DescribeTable("when deploying a SonataFlowPlatform CR with platform broker", func(testcaseDir string, brokerInAnotherNamespace bool) { - By("Deploy the broker") - brokerName := "default" - brokerNamespace := targetNamespace - if brokerInAnotherNamespace { - brokerNamespace = targetNamespace2 - } - GinkgoWriter.Println(fmt.Sprintf("testcaseDir=%v, brokerNamespace = %s", testcaseDir, brokerNamespace)) - cmd := exec.Command("kubectl", "create", "-n", brokerNamespace, "-f", filepath.Join(projectDir, - testcaseDir, "broker")) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for the broker to be ready") - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "broker", brokerName, "-n", brokerNamespace, "--for", "condition=Ready=True", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - - By("Deploy the SonataFlowPlatform CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - manifestsUpdated := strings.ReplaceAll(string(manifests), "${BROKER_NAMESPACE}", brokerNamespace) - cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer([]byte(manifestsUpdated)) - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Wait for SonatatFlowPlatform CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() error { - cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", "--timeout=5s") - _, err = utils.Run(cmd) - return err - }, 10*time.Minute, 5).Should(Succeed()) - - GinkgoWriter.Println("waitForPodRestartCompletion") - waitForPodRestartCompletion("app.kubernetes.io/name=jobs-service", targetNamespace) - GinkgoWriter.Println("waitForPodRestartCompletion done") - - By("Evaluate status of all service's health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, targetNamespace) - } - By("Evaluate triggers and sinkbindings for DI and JS") - cmd = exec.Command("kubectl", "get", "sonataflowplatform", "sonataflow-platform", "-n", targetNamespace, "-ojsonpath={.status.triggers}") - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - var triggers []operatorapi.SonataFlowPlatformTriggerRef - err = json.Unmarshal(output, &triggers) - Expect(err).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-error-", constants.KogitoProcessInstancesEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-node-", constants.KogitoProcessInstancesEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-state-", constants.KogitoProcessInstancesEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-variable-", constants.KogitoProcessInstancesEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-process-definition-", constants.KogitoProcessDefinitionsEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "data-index-jobs-", constants.KogitoJobsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "jobs-service-create-job-", constants.JobServiceJobEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, "jobs-service-delete-job-", constants.JobServiceJobEventsPath, brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifySinkBinding("sonataflow-platform-jobs-service-sb", targetNamespace, brokerName)).NotTo(HaveOccurred()) - - By("Deploy the SonataFlow CR") - cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", filepath.Join(projectDir, - testcaseDir, "sonataflow")) - manifests, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace, prebuiltWorkflows.CallBack.Name, prebuiltWorkflows.CallBack.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Evaluate status of SonataFlow CR") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowIsInRunningState(prebuiltWorkflows.CallBack.Name, targetNamespace) - }, 5*time.Minute, 5).Should(BeTrue()) - - By("Evaluate triggers and sinkbindings for the workflow") - cmd = exec.Command("kubectl", "get", "sonataflow", prebuiltWorkflows.CallBack.Name, "-n", targetNamespace, "-ojsonpath={.status.triggers}") - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = json.Unmarshal(output, &triggers) - Expect(err).NotTo(HaveOccurred()) - Expect(verifyTrigger(triggers, prebuiltWorkflows.CallBack.Name, "", brokerNamespace, brokerName)).NotTo(HaveOccurred()) - Expect(verifySinkBinding(fmt.Sprintf("%s-sb", prebuiltWorkflows.CallBack.Name), targetNamespace, brokerName)).NotTo(HaveOccurred()) - }, - Entry("and with broker and platform in the same namespace", test.GetPathFromE2EDirectory("platform", "services", "gitops", "knative", "platform-level-broker"), false), - Entry("and with broker and platform in a separate namespace", test.GetPathFromE2EDirectory("platform", "services", "gitops", "knative", "platform-level-broker"), true), - ) - - DescribeTable("when deploying a SonataFlowPlatform combined with HPA for the Data Index", Label("data-index-hpa"), func(testcaseDir string, dataIndexHPAPath string, createHPABeforePlatform bool) { - if createHPABeforePlatform { - By("Create the data index HPA before the platform") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(dataIndexHPAPath, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - } - - By("Deploy the platform and database CRs") - EventuallyWithOffset(1, func() error { - return kubectlApplyKustomizeOnCluster(testcaseDir, targetNamespace) - }, 2*time.Minute, time.Second).Should(Succeed()) - - By("Wait for SonataFlowPlatform CR to complete deployments") - EventuallyWithOffset(1, func() error { - return verifyDataIndexAndJobsServiceAreReady(targetNamespace, "5s") - }, 10*time.Minute, 5).Should(Succeed()) - - By("Evaluate status of all service's health endpoint") - verifyDataIndexAndJobsServiceAreHealthy(targetNamespace) - - if createHPABeforePlatform { - By("Check that the Data Index deployment has 3 replicas since the HPA was already created") - EventuallyWithOffset(3, func() bool { - return verifyDeploymentReplicas("sonataflow-platform-data-index-service", targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - } else { - By("Check that the Data Index deployment has 1 replica before creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas("sonataflow-platform-data-index-service", targetNamespace, int32(1)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("Create the data index HPA after the platform") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(dataIndexHPAPath, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Check that the data index has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas("sonataflow-platform-data-index-service", targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - } - - By("Delete the data index HPA") - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(dataIndexHPAPath, targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(Succeed()) - - By("Check that the data index has 1 replica after deleting the HPA") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas("sonataflow-platform-data-index-service", targetNamespace, int32(1)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - }, - - Entry("and the HPA is created after the platform", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr"), test.GetPathFromE2EDirectory("platform", "hpa", "generic-data-index-service-hpa.yaml"), false), - Entry("and the HPA is created before the platform", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr"), test.GetPathFromE2EDirectory("platform", "hpa", "generic-data-index-service-hpa.yaml"), true), - ) - - DescribeTable("when deploying a SonataFlowPlatform with PDB configured for the Data Index", Label("data-index-pdb"), func(testcaseDir string, dataIndexPatchReplicas string, shouldHavePDBAfterPatch bool, shouldHaveDisruptionsAllowedAfterPatch string, shouldHaveDisruptionsAllowedNumberAfterPatch int32) { - sfpName := "sonataflow-platform" - dataIndexServiceName := "sonataflow-platform-data-index-service" - expectedPDB := dataIndexServiceName - - By("Deploy the platform and database CRs") - EventuallyWithOffset(1, func() error { - return kubectlApplyKustomizeOnCluster(testcaseDir, targetNamespace) - }, 2*time.Minute, time.Second).Should(Succeed()) - - By("Wait for SonataFlowPlatform CR to complete the deployments") - EventuallyWithOffset(1, func() error { - return verifyDataIndexAndJobsServiceAreReady(targetNamespace, "5s") - }, 10*time.Minute, 5).Should(Succeed()) - - By("Evaluate status of all service's health endpoint") - verifyDataIndexAndJobsServiceAreHealthy(targetNamespace) - - By("Check that the Data Index deployment has 3 replicas as expected") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas(dataIndexServiceName, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget for the Data Index was created") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(dataIndexServiceName, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget's DisruptionAllowed condition is True") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(expectedPDB, targetNamespace, "DisruptionAllowed", "True") - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is allowing 2 disruptions") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(expectedPDB, targetNamespace, int32(2)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By(fmt.Sprintf("scale the Data Index service to Replicas = %s", dataIndexPatchReplicas)) - EventuallyWithOffset(1, func() error { - return patchSFPDataIndexReplicas(sfpName, targetNamespace, dataIndexPatchReplicas) - }, 3*time.Minute, 30*time.Second).Should(Succeed()) - - if shouldHavePDBAfterPatch { - By("check that the PodDisruptionBudget for the Data Index still exists") - } else { - By("check that the PodDisruptionBudget for the Data Index was removed") - } - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(dataIndexServiceName, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(Equal(shouldHavePDBAfterPatch)) - - if shouldHavePDBAfterPatch { - By(fmt.Sprintf("check that the PodDisruptionBudget's DisruptionAllowed condition in the expected status = %s", shouldHaveDisruptionsAllowedAfterPatch)) - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(expectedPDB, targetNamespace, "DisruptionAllowed", shouldHaveDisruptionsAllowedAfterPatch) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By(fmt.Sprintf("check that the PodDisruptionBudget is allowing the disruptions number = %s", strconv.Itoa(int(shouldHaveDisruptionsAllowedNumberAfterPatch)))) - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(expectedPDB, targetNamespace, shouldHaveDisruptionsAllowedNumberAfterPatch) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - } - }, - - Entry("and the Data Index is rescaled to 4 replicas", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb"), "4", true, "True", int32(3)), - Entry("and the Data Index is rescaled to 2 replicas", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb"), "2", true, "True", int32(1)), - Entry("and the Data Index is rescaled to 1 replicas", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb"), "1", false, "UnUsed", int32(-1)), - ) - - DescribeTable("when deploying a SonataFlowPlatform with PDB configured for the Data Index combined with HPA", Label("data-index-pdb-with-hpa"), func(testcaseDir string, hpaPatchReplicas string, shouldHavePDBAfterPatch bool, shouldHaveDisruptionsAllowedAfterPatch string, shouldHaveDisruptionsAllowedNumberAfterPatch int32) { - dataIndexServiceName := "sonataflow-platform-data-index-service" - expectedPDB := dataIndexServiceName - - By("Deploy the platform and database CRs") - EventuallyWithOffset(1, func() error { - return kubectlApplyKustomizeOnCluster(testcaseDir, targetNamespace) - }, 2*time.Minute, time.Second).Should(Succeed()) - - By("Wait for SonataFlowPlatform CR to complete the deployments") - EventuallyWithOffset(1, func() error { - return verifyDataIndexAndJobsServiceAreReady(targetNamespace, "5s") - }, 10*time.Minute, 5).Should(Succeed()) - - By("Evaluate status of all service's health endpoint") - verifyDataIndexAndJobsServiceAreHealthy(targetNamespace) - - By("Check that the Data Index deployment has 2 replicas as expected from the initial HPA configuration") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas(dataIndexServiceName, targetNamespace, int32(2)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget for the Data Index was created") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(dataIndexServiceName, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget's DisruptionAllowed condition is True") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(expectedPDB, targetNamespace, "DisruptionAllowed", "True") - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is allowing 1 disruption") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(expectedPDB, targetNamespace, int32(1)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By(fmt.Sprintf("patch the HPA minReplicas to: %s", hpaPatchReplicas)) - EventuallyWithOffset(1, func() error { - return patchHPAMinReplicas("sonataflow-platform-data-index-service-hpa", targetNamespace, hpaPatchReplicas) - }, 3*time.Minute, 30*time.Second).Should(Succeed()) - - if shouldHavePDBAfterPatch { - By("check that the PodDisruptionBudget for the Data Index still exists after patching the HPA") - } else { - By("check that the PodDisruptionBudget for the Data Index was removed after patching the HPA") - } - - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(dataIndexServiceName, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(Equal(shouldHavePDBAfterPatch)) - - if shouldHavePDBAfterPatch { - By(fmt.Sprintf("check that the PodDisruptionBudget's DisruptionAllowed condition in the expected status = %s", shouldHaveDisruptionsAllowedAfterPatch)) - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(expectedPDB, targetNamespace, "DisruptionAllowed", shouldHaveDisruptionsAllowedAfterPatch) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By(fmt.Sprintf("check that the PodDisruptionBudget is allowing the disruptions number = %s", strconv.Itoa(int(shouldHaveDisruptionsAllowedNumberAfterPatch)))) - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(expectedPDB, targetNamespace, shouldHaveDisruptionsAllowedNumberAfterPatch) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - } - }, - - Entry("and the HPA minReplicas is configured with 4", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb_and_hpa"), "4", true, "True", int32(3)), - Entry("and the HPA minReplicas is configured with 3", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb_and_hpa"), "3", true, "True", int32(2)), - Entry("and the HPA minReplicas is configured with 1", test.GetPathFromE2EDirectory("platform", "persistence", "generic_from_platform_cr_with_pdb_and_hpa"), "1", false, "UnUsed", int32(-1)), - ) -}) - -func verifyDataIndexAndJobsServiceAreReady(namespace string, timeout string) error { - cmd := exec.Command("kubectl", "wait", "pod", "-n", namespace, "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "--for", "condition=Ready", fmt.Sprintf("--timeout=%s", timeout)) - _, err := utils.Run(cmd) - return err -} - -func verifyDataIndexAndJobsServiceAreHealthy(namespace string) { - cmd := exec.Command("kubectl", "get", "pod", "-l", "app.kubernetes.io/name in (jobs-service,data-index-service)", "-n", namespace, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - for _, pn := range strings.Split(string(output), " ") { - verifyHealthStatusInPod(pn, namespace) - } -} diff --git a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts-persistence.yaml b/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts-persistence.yaml deleted file mode 100644 index 23edf2ff..00000000 --- a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts-persistence.yaml +++ /dev/null @@ -1,98 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: preview -spec: - podTemplate: - replicas: 0 - # We need the persistence entry to build this image with the right extensions - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - databaseSchema: callbackstatetimeouts-persistence - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts.yaml b/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts.yaml deleted file mode 100644 index 510ded31..00000000 --- a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-callbackstatetimeouts.yaml +++ /dev/null @@ -1,86 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: preview -spec: - podTemplate: - replicas: 0 - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-greetings.yaml b/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-greetings.yaml deleted file mode 100644 index 158dcd9e..00000000 --- a/test/e2e/testdata/before-suite/sonataflow.org_v1alpha08_sonataflow-greetings.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greetings - annotations: - sonataflow.org/description: Greetings example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: preview - labels: - test: test -spec: - podTemplate: - replicas: 0 - flow: - start: HelloWorld - states: - - name: HelloWorld - type: inject - data: - message: Hello World - end: true diff --git a/test/e2e/testdata/order-processing/01_v1_configmap_subflows.yaml b/test/e2e/testdata/order-processing/01_v1_configmap_subflows.yaml deleted file mode 100644 index fe896c10..00000000 --- a/test/e2e/testdata/order-processing/01_v1_configmap_subflows.yaml +++ /dev/null @@ -1,85 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ConfigMap -apiVersion: v1 -metadata: - name: orderprocessing-subflows -data: - fraud-handling.sw.yaml: |- - id: fraudhandling - name: Fraud Handling - expressionLang: jsonpath - start: FraudHandling - version: "1.0" - events: - - kind: produced - name: FraudEvaluation - type: fraudEvaluation - source: fraudEvaluation - states: - - name: FraudHandling - type: switch - dataConditions: - - condition: "{{ $.[?(@.total > 1000)] }}" - transition: FraudVerificationNeeded - - condition: "{{ $.[?(@.total <= 1000)] }}" - end: true - - name: FraudVerificationNeeded - type: inject - data: - fraudEvaluation: true - end: - produceEvents: - - eventRef: FraudEvaluation - shipping-handling.sw.yaml: |- - id: shippinghandling - name: Shipping Handling - expressionLang: jsonpath - start: ShippingHandling - version: "1.0" - events: - - kind: produced - name: InternationalShippingOrder - type: internationalShipping - source: internationalShipping - - kind: produced - name: DomesticShippingOrder - type: domesticShipping - source: domesticShipping - states: - - name: ShippingHandling - type: switch - dataConditions: - - condition: "${ $.[?(@.country == 'US')] }" - transition: DomesticShipping - - condition: "${ $.[?(@.country != 'US')] }" - transition: InternationalShipping - - name: DomesticShipping - type: inject - data: - shipping: "domestic" - end: - produceEvents: - - eventRef: DomesticShippingOrder - - name: InternationalShipping - type: inject - data: - shipping: "international" - end: - produceEvents: - - eventRef: "InternationalShippingOrder" diff --git a/test/e2e/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml b/test/e2e/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml deleted file mode 100644 index b9b810b3..00000000 --- a/test/e2e/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: v1 -kind: Service -metadata: - name: event-listener - labels: - app: event-listener -spec: - selector: - app: event-listener - ports: - - name: http - port: 80 - targetPort: 8080 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: event-listener - labels: - app: event-listener -spec: - replicas: 1 - selector: - matchLabels: - app: event-listener - template: - metadata: - labels: - app: event-listener - spec: - containers: - - name: event-listener - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - capabilities: - drop: - - ALL - seccompProfile: - type: "RuntimeDefault" - image: gcr.io/knative-releases/knative.dev/eventing/cmd/event_display:latest - ports: - - containerPort: 8080 diff --git a/test/e2e/testdata/order-processing/03_discovery_role.yaml b/test/e2e/testdata/order-processing/03_discovery_role.yaml deleted file mode 100644 index 5c35ab6a..00000000 --- a/test/e2e/testdata/order-processing/03_discovery_role.yaml +++ /dev/null @@ -1,78 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kogito-discovery-role -rules: - - apiGroups: - - "" - resources: - - pods - - services - verbs: - - get - - list - - apiGroups: - - apps - resources: - - deployments - - statefulsets - verbs: - - get - - list - - apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - get - - list - - apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - get - - list - - apiGroups: - - apps.openshift.io - resources: - - deploymentconfigs - verbs: - - get - - list - - apiGroups: - - serving.knative.dev - resources: - - services - verbs: - - get - - list ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: kogito-discovery-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kogito-discovery-role -subjects: - - kind: ServiceAccount - name: default diff --git a/test/e2e/testdata/order-processing/04_v1_configmap_properties.yaml b/test/e2e/testdata/order-processing/04_v1_configmap_properties.yaml deleted file mode 100644 index 5392bd27..00000000 --- a/test/e2e/testdata/order-processing/04_v1_configmap_properties.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ConfigMap -apiVersion: v1 -metadata: - name: orderprocessing-props -data: - application.properties: | - quarkus.log.level = INFO - mp.messaging.outgoing.kogito_outgoing_stream.url = ${kubernetes:services.v1/event-listener} diff --git a/test/e2e/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml b/test/e2e/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml deleted file mode 100644 index b8cae65c..00000000 --- a/test/e2e/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml +++ /dev/null @@ -1,56 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: orderprocessing - annotations: - sonataflow.org/description: Workflow for processing Orders and produce Logistics Events - sonataflow.org/version: 1.0.0 - sonataflow.org/expressionLang: jsonpath - sonataflow.org/profile: dev -spec: - resources: - configMaps: - - configMap: - name: orderprocessing-subflows - flow: - start: ReceiveOrder - events: - - kind: consumed - name: OrderEvent - type: orderEvent - source: orderEvent - states: - - name: ReceiveOrder - type: event - onEvents: - - eventRefs: - - "OrderEvent" - transition: ProcessOrder - - name: ProcessOrder - type: parallel - branches: - - name: HandleFraudEvaluation - actions: - - subFlowRef: fraudhandling - - name: HandleShippingType - actions: - - subFlowRef: shippinghandling - completionType: allOf - end: true diff --git a/test/e2e/testdata/order-processing/README.md b/test/e2e/testdata/order-processing/README.md deleted file mode 100644 index dca6221f..00000000 --- a/test/e2e/testdata/order-processing/README.md +++ /dev/null @@ -1,20 +0,0 @@ - - -# Order Processing Example - -See: https://github.com/kiegroup/kogito-examples/tree/main/serverless-workflow-examples/serverless-workflow-order-processing diff --git a/test/e2e/testdata/platform/hpa/generic-data-index-service-hpa.yaml b/test/e2e/testdata/platform/hpa/generic-data-index-service-hpa.yaml deleted file mode 100644 index c897cc9e..00000000 --- a/test/e2e/testdata/platform/hpa/generic-data-index-service-hpa.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: sonataflow-platform-data-index-service-hpa -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: sonataflow-platform-data-index-service - minReplicas: 3 - maxReplicas: 5 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/test/e2e/testdata/platform/noservices/gitops/ephemeral/00-broker.yaml b/test/e2e/testdata/platform/noservices/gitops/ephemeral/00-broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/platform/noservices/gitops/ephemeral/00-broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/platform/noservices/gitops/ephemeral/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/noservices/gitops/ephemeral/02-sonataflow_platform.yaml deleted file mode 100644 index 066fb9e3..00000000 --- a/test/e2e/testdata/platform/noservices/gitops/ephemeral/02-sonataflow_platform.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - build: - template: - buildArgs: - - name: QUARKUS_EXTENSION - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/test/e2e/testdata/platform/noservices/gitops/ephemeral/kustomization.yaml b/test/e2e/testdata/platform/noservices/gitops/ephemeral/kustomization.yaml deleted file mode 100644 index 0656b335..00000000 --- a/test/e2e/testdata/platform/noservices/gitops/ephemeral/kustomization.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 00-broker.yaml - - 02-sonataflow_platform.yaml - - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/noservices/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/noservices/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/noservices/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml deleted file mode 100644 index c0dbfdf2..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - services: - dataIndex: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml deleted file mode 100644 index 48d72cbd..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/01-postgres.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/02-sonataflow_platform.yaml deleted file mode 100644 index d43db8d7..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/02-sonataflow_platform.yaml +++ /dev/null @@ -1,66 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - services: - dataIndex: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - replicas: 3 - podDisruptionBudget: - minAvailable: 1 - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/kustomization.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/kustomization.yaml deleted file mode 100644 index 48d72cbd..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/01-postgres.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/02-sonataflow_platform.yaml deleted file mode 100644 index 799c6554..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/02-sonataflow_platform.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - services: - dataIndex: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - podDisruptionBudget: - minAvailable: 1 - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: false - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/03-data-index-service-hpa.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/03-data-index-service-hpa.yaml deleted file mode 100644 index 27c2408d..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/03-data-index-service-hpa.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: sonataflow-platform-data-index-service-hpa -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: sonataflow-platform-data-index-service - minReplicas: 2 - maxReplicas: 5 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/kustomization.yaml b/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/kustomization.yaml deleted file mode 100644 index c0b08ff0..00000000 --- a/test/e2e/testdata/platform/persistence/generic_from_platform_cr_with_pdb_and_hpa/kustomization.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-data-index-service-hpa.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/01-postgres.yaml b/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/kustomization.yaml b/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/kustomization.yaml deleted file mode 100644 index eaea57c0..00000000 --- a/test/e2e/testdata/platform/persistence/job_based_db_migration/pg-service/kustomization.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/01-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/01-sonataflow_platform.yaml deleted file mode 100644 index aa234f3c..00000000 --- a/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/01-sonataflow_platform.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: job - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - jobService: - enabled: true - persistence: - dbMigrationStrategy: job - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD diff --git a/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/kustomization.yaml b/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/kustomization.yaml deleted file mode 100644 index 601a6418..00000000 --- a/test/e2e/testdata/platform/persistence/job_based_db_migration/sonataflow-platform/kustomization.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true diff --git a/test/e2e/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml b/test/e2e/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml deleted file mode 100644 index aeb44768..00000000 --- a/test/e2e/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml +++ /dev/null @@ -1,79 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: USER - passwordKey: PASSWORD - serviceRef: - name: no-db-exists - port: 5432 - databaseName: find-me - services: - dataIndex: - enabled: false - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: false - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/persistence/overwritten_by_services/kustomization.yaml b/test/e2e/testdata/platform/persistence/overwritten_by_services/kustomization.yaml deleted file mode 100644 index 48d72cbd..00000000 --- a/test/e2e/testdata/platform/persistence/overwritten_by_services/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/persistence/service_based_db_migration/01-postgres.yaml b/test/e2e/testdata/platform/persistence/service_based_db_migration/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/persistence/service_based_db_migration/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/persistence/service_based_db_migration/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/persistence/service_based_db_migration/02-sonataflow_platform.yaml deleted file mode 100644 index 01b77b11..00000000 --- a/test/e2e/testdata/platform/persistence/service_based_db_migration/02-sonataflow_platform.yaml +++ /dev/null @@ -1,69 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/persistence/service_based_db_migration/kustomization.yaml b/test/e2e/testdata/platform/persistence/service_based_db_migration/kustomization.yaml deleted file mode 100644 index 48d72cbd..00000000 --- a/test/e2e/testdata/platform/persistence/service_based_db_migration/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml deleted file mode 100644 index 49c82e21..00000000 --- a/test/e2e/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - template: - buildArgs: - - name: QUARKUS_EXTENSION - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: false - jobService: - enabled: false diff --git a/test/e2e/testdata/platform/services/dev/ephemeral/kustomization.yaml b/test/e2e/testdata/platform/services/dev/ephemeral/kustomization.yaml deleted file mode 100644 index d55973fe..00000000 --- a/test/e2e/testdata/platform/services/dev/ephemeral/kustomization.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 02-sonataflow_platform.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 3fd52b39..00000000 --- a/test/e2e/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: dev -spec: - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/dev/postgreSQL/01-postgres.yaml b/test/e2e/testdata/platform/services/dev/postgreSQL/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/services/dev/postgreSQL/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml deleted file mode 100644 index ee1942f1..00000000 --- a/test/e2e/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - template: - buildArgs: - - name: QUARKUS_EXTENSIONS - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - services: - dataIndex: - enabled: false - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: false - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/platform/services/dev/postgreSQL/kustomization.yaml b/test/e2e/testdata/platform/services/dev/postgreSQL/kustomization.yaml deleted file mode 100644 index 48d72cbd..00000000 --- a/test/e2e/testdata/platform/services/dev/postgreSQL/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 3fd52b39..00000000 --- a/test/e2e/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: dev -spec: - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml b/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml deleted file mode 100644 index 57e9735d..00000000 --- a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowClusterPlatform -metadata: - name: cluster -spec: - platformRef: - name: sonataflow-platform - namespace: test-ns diff --git a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/02-sonataflow_platform.yaml deleted file mode 100644 index 76de2a4f..00000000 --- a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/02-sonataflow_platform.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - template: - buildArgs: - - name: QUARKUS_EXTENSION - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - jobService: - enabled: true diff --git a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/kustomization.yaml deleted file mode 100644 index f468cd8f..00000000 --- a/test/e2e/testdata/platform/services/gitops/cluster-wide-ephemeral/kustomization.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-sonataflow_clusterplatform.yaml - - 02-sonataflow_platform.yaml diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/02-sonataflow_platform.yaml deleted file mode 100644 index 0377ef62..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/02-sonataflow_platform.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - template: - buildArgs: - - name: QUARKUS_EXTENSION - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: false diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/kustomization.yaml deleted file mode 100644 index f775d25f..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 02-sonataflow_platform.yaml - - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/02-sonataflow_platform.yaml deleted file mode 100644 index 1784c72a..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/02-sonataflow_platform.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - template: - buildArgs: - - name: QUARKUS_EXTENSION - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - jobService: - enabled: false diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/kustomization.yaml deleted file mode 100644 index f775d25f..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 02-sonataflow_platform.yaml - - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/02-sonataflow_platform.yaml deleted file mode 100644 index d6af1ae9..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/02-sonataflow_platform.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - jobService: - enabled: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/kustomization.yaml deleted file mode 100644 index f775d25f..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 02-sonataflow_platform.yaml - - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow-no-broker/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/00-broker.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/00-broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/00-broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/02-sonataflow_platform.yaml deleted file mode 100644 index 76482ecc..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/02-sonataflow_platform.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - jobService: - enabled: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/kustomization.yaml deleted file mode 100644 index f775d25f..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 02-sonataflow_platform.yaml - - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral/00-broker.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral/00-broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral/00-broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral/02-sonataflow_platform.yaml deleted file mode 100644 index 76482ecc..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral/02-sonataflow_platform.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - jobService: - enabled: true diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral/kustomization.yaml deleted file mode 100644 index 9e38a081..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 00-broker.yaml - - 02-sonataflow_platform.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/01-postgres.yaml b/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/02-sonataflow_platform.yaml deleted file mode 100644 index b452ae61..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/02-sonataflow_platform.yaml +++ /dev/null @@ -1,90 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - namespace: ${BROKER_NAMESPACE} - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" - jobService: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" diff --git a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/broker/broker.yaml b/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/broker/broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/broker/broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/kustomization.yaml deleted file mode 100644 index c43155d5..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/kustomization.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index abe67575..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/platform-level-broker/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/01-postgres.yaml b/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/02-sonataflow_platform.yaml deleted file mode 100644 index 6237c383..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/02-sonataflow_platform.yaml +++ /dev/null @@ -1,104 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - source: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: di-source - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" - jobService: - enabled: true - source: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: js-source - sink: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: js-sink - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" diff --git a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/broker/00-broker.yaml b/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/broker/00-broker.yaml deleted file mode 100644 index cffaa6cd..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/broker/00-broker.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default - labels: - test: test-e2e -spec: {} ---- -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: di-source - labels: - test: test-e2e -spec: {} ---- -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: js-sink - labels: - test: test-e2e -spec: {} ---- -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: js-source - labels: - test: test-e2e -spec: {} diff --git a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/kustomization.yaml deleted file mode 100644 index c43155d5..00000000 --- a/test/e2e/testdata/platform/services/gitops/knative/service-level-broker/kustomization.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/postgreSQL/00-broker.yaml b/test/e2e/testdata/platform/services/gitops/postgreSQL/00-broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/platform/services/gitops/postgreSQL/00-broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/platform/services/gitops/postgreSQL/01-postgres.yaml b/test/e2e/testdata/platform/services/gitops/postgreSQL/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/platform/services/gitops/postgreSQL/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/platform/services/gitops/postgreSQL/02-sonataflow_platform.yaml b/test/e2e/testdata/platform/services/gitops/postgreSQL/02-sonataflow_platform.yaml deleted file mode 100644 index b11ef02d..00000000 --- a/test/e2e/testdata/platform/services/gitops/postgreSQL/02-sonataflow_platform.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" - jobService: - enabled: true - persistence: - dbMigrationStrategy: service - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - container: - env: - - name: MY_CUSTOM_VARIABLE - value: "OKAY" - - name: QUARKUS_DATASOURCE_PASSWORD - # This value should not be used since it's already set by the operator. If used, the test will fail. - value: "SHOULD_NOT_BE_USED" diff --git a/test/e2e/testdata/platform/services/gitops/postgreSQL/kustomization.yaml b/test/e2e/testdata/platform/services/gitops/postgreSQL/kustomization.yaml deleted file mode 100644 index 60b8599a..00000000 --- a/test/e2e/testdata/platform/services/gitops/postgreSQL/kustomization.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - 00-broker.yaml - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/platform/services/gitops/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/platform/services/gitops/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 8fb54e5a..00000000 --- a/test/e2e/testdata/platform/services/gitops/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,95 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - persistence: - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=callbackstatetimeouts-persistence - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow.yaml b/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow.yaml deleted file mode 100644 index 52821a63..00000000 --- a/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greetings - annotations: - sonataflow.org/description: Greetings example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops - labels: - test: test -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - resources: - limits: - cpu: 500m - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - flow: - start: HelloWorld - states: - - name: HelloWorld - type: inject - data: - message: Hello World - end: true diff --git a/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml b/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml deleted file mode 100644 index ac5f9d4b..00000000 --- a/test/e2e/testdata/workflows/greetings/01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: greetings-hpa -spec: - scaleTargetRef: - apiVersion: sonataflow.org/v1alpha08 - kind: SonataFlow - name: greetings - minReplicas: 3 - maxReplicas: 4 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/test/e2e/testdata/workflows/persistence/by_service/01-postgres.yaml b/test/e2e/testdata/workflows/persistence/by_service/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/workflows/persistence/by_service/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/workflows/persistence/by_service/02-sonataflow_platform.yaml b/test/e2e/testdata/workflows/persistence/by_service/02-sonataflow_platform.yaml deleted file mode 100644 index db0258d4..00000000 --- a/test/e2e/testdata/workflows/persistence/by_service/02-sonataflow_platform.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/test/e2e/testdata/workflows/persistence/by_service/03-configmap_callbackstatetimeouts-props.yaml b/test/e2e/testdata/workflows/persistence/by_service/03-configmap_callbackstatetimeouts-props.yaml deleted file mode 100644 index 8bad3cc8..00000000 --- a/test/e2e/testdata/workflows/persistence/by_service/03-configmap_callbackstatetimeouts-props.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: v1 -data: - application.properties: | - # set the flyway initialization in the WF ConfigMap - quarkus.flyway.migrate-at-start=true -kind: ConfigMap -metadata: - labels: - app: callbackstatetimeouts-persistence - name: callbackstatetimeouts-persistence-props diff --git a/test/e2e/testdata/workflows/persistence/by_service/04-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/workflows/persistence/by_service/04-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 80b0349b..00000000 --- a/test/e2e/testdata/workflows/persistence/by_service/04-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,109 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - databaseSchema: callbackstatetimeouts-persistence - podTemplate: - container: - image: replaceme - replicas: 0 - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/persistence/by_service/kustomization.yaml b/test/e2e/testdata/workflows/persistence/by_service/kustomization.yaml deleted file mode 100644 index 09e11e47..00000000 --- a/test/e2e/testdata/workflows/persistence/by_service/kustomization.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-configmap_callbackstatetimeouts-props.yaml - - 04-sonataflow_callbackstatetimeouts.sw.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/01-postgres.yaml b/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml b/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml deleted file mode 100644 index f9349a0f..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: my-secret - userKey: MY_USER - passwordKey: MY_PASSWORD - serviceRef: - name: db_not_defined - port: 3456 - databaseName: db_name - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 65370ad2..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,113 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - databaseSchema: callbackstatetimeouts-persistence - podTemplate: - replicas: 0 - container: - image: replaceme - env: - # set the flyway initialization in the WF container env - - name: QUARKUS_FLYWAY_MIGRATE_AT_START - value: "true" - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/kustomization.yaml b/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/kustomization.yaml deleted file mode 100644 index eab76a26..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_overwritten_by_service/kustomization.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-sonataflow_callbackstatetimeouts.sw.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/00-broker.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/00-broker.yaml deleted file mode 100644 index e809e629..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/00-broker.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - name: default -spec: {} diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/01-postgres.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml deleted file mode 100644 index 8495db1e..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml +++ /dev/null @@ -1,73 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - eventing: - broker: - ref: - apiVersion: eventing.knative.dev/v1 - kind: Broker - name: default - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] - jobService: - enabled: true - persistence: - dbMigrationStrategy: service - podTemplate: - initContainers: - - name: init-postgres - image: registry.access.redhat.com/ubi9/ubi-micro:latest - imagePullPolicy: IfNotPresent - command: - [ - "sh", - "-c", - 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;', - ] diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/03-configmap_callbackstatetimeouts-props.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/03-configmap_callbackstatetimeouts-props.yaml deleted file mode 100644 index 5ced6ba2..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/03-configmap_callbackstatetimeouts-props.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: v1 -data: - application.properties: | - # set the flyway initialization in the WF ConfigMap - quarkus.flyway.migrate-at-start=true -kind: ConfigMap -metadata: - labels: - app: callbackstatetimeouts-persistence - name: callbackstatetimeouts-persistence-props diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/04-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/04-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index 1f1089df..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/04-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - container: - image: replaceme - replicas: 0 - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/kustomization.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/kustomization.yaml deleted file mode 100644 index 808b597b..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_di_and_js_services/kustomization.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 00-broker.yaml - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-configmap_callbackstatetimeouts-props.yaml - - 04-sonataflow_callbackstatetimeouts.sw.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/01-postgres.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml deleted file mode 100644 index a79aee3c..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml deleted file mode 100644 index da10f52b..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml +++ /dev/null @@ -1,91 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - env: - - name: QUARKUS_FLYWAY_MIGRATE_AT_START - value: "true" - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/kustomization.yaml b/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/kustomization.yaml deleted file mode 100644 index e991e4d5..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_with_no_persistence_required/kustomization.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/01-postgres.yaml b/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/01-postgres.yaml deleted file mode 100644 index 89f6e6fc..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/01-postgres.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: postgres - template: - metadata: - labels: - app.kubernetes.io/name: postgres - spec: - containers: - - name: postgres - image: postgres:13.2-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - volumeMounts: - - name: storage - mountPath: /var/lib/postgresql/data - envFrom: - - secretRef: - name: postgres-secrets - readinessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - livenessProbe: - exec: - command: ["pg_isready"] - initialDelaySeconds: 15 - timeoutSeconds: 2 - resources: - limits: - memory: "256Mi" - cpu: "500m" - volumes: - - name: storage - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: postgres - name: postgres -spec: - selector: - app.kubernetes.io/name: postgres - ports: - - port: 5432 diff --git a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml b/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml deleted file mode 100644 index a79aee3c..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - persistence: - postgresql: - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - serviceRef: - name: postgres - port: 5432 - databaseName: sonataflow - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" diff --git a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml deleted file mode 100644 index b4f6a69b..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: callbackstatetimeouts-persistence - annotations: - sonataflow.org/description: Callback State Timeouts Example k8s - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - env: - # set the flyway initialization in the WF container env - - name: QUARKUS_FLYWAY_MIGRATE_AT_START - value: "true" - flow: - start: PrintStartMessage - events: - - name: callbackEvent - source: "" - type: callback_event_type - functions: - - name: systemOut - type: custom - operation: sysout - states: - - name: PrintStartMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has started."}' - transition: CallbackState - - name: CallbackState - type: callback - action: - name: callbackAction - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has executed the callbackFunction."}' - eventRef: callbackEvent - transition: CheckEventArrival - timeouts: - eventTimeout: PT30S - - name: CheckEventArrival - type: switch - dataConditions: - - condition: "${ .eventData != null }" - transition: EventArrived - defaultCondition: - transition: EventNotArrived - - name: EventArrived - type: inject - data: - exitMessage: "The callback event has arrived." - transition: PrintExitMessage - - name: EventNotArrived - type: inject - data: - exitMessage: "The callback event has not arrived, and the timeout has overdue." - transition: PrintExitMessage - - name: PrintExitMessage - type: operation - actions: - - name: printSystemOut - functionRef: - refName: systemOut - arguments: - message: '${"callback-state-timeouts: " + $WORKFLOW.instanceId + " has finalized. " + .exitMessage + " eventData: " + .eventData}' - end: true diff --git a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/kustomization.yaml b/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/kustomization.yaml deleted file mode 100644 index eab76a26..00000000 --- a/test/e2e/testdata/workflows/persistence/from_platform_without_di_and_js_services/kustomization.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-postgres.yaml - - 02-sonataflow_platform.yaml - - 03-sonataflow_callbackstatetimeouts.sw.yaml - -generatorOptions: - disableNameSuffixHash: true - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DATABASE=sonataflow - - PGDATA=/var/lib/pgsql/data/userdata - -sortOptions: - order: fifo diff --git a/test/e2e/testdata/workflows/prometheus/k8s_deployment/01-sonataflow_platform.yaml b/test/e2e/testdata/workflows/prometheus/k8s_deployment/01-sonataflow_platform.yaml deleted file mode 100644 index 43f893d5..00000000 --- a/test/e2e/testdata/workflows/prometheus/k8s_deployment/01-sonataflow_platform.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - monitoring: - enabled: true diff --git a/test/e2e/testdata/workflows/prometheus/k8s_deployment/02-sonataflow_greetings.yaml b/test/e2e/testdata/workflows/prometheus/k8s_deployment/02-sonataflow_greetings.yaml deleted file mode 100644 index 5db7ac13..00000000 --- a/test/e2e/testdata/workflows/prometheus/k8s_deployment/02-sonataflow_greetings.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greetings - annotations: - sonataflow.org/description: Greetings example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: gitops - labels: - test: test -spec: - podTemplate: - replicas: 0 - container: - image: replaceme - flow: - start: HelloWorld - states: - - name: HelloWorld - type: inject - data: - message: Hello World - end: true diff --git a/test/e2e/testdata/workflows/prometheus/k8s_deployment/kustomization.yaml b/test/e2e/testdata/workflows/prometheus/k8s_deployment/kustomization.yaml deleted file mode 100644 index e748413b..00000000 --- a/test/e2e/testdata/workflows/prometheus/k8s_deployment/kustomization.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -resources: - - 01-sonataflow_platform.yaml - - 02-sonataflow_greetings.yaml - -sortOptions: - order: fifo diff --git a/test/e2e/workflow_test.go b/test/e2e/workflow_test.go deleted file mode 100644 index 79eeb02d..00000000 --- a/test/e2e/workflow_test.go +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 e2e - -import ( - "bytes" - "fmt" - "math/rand" - "os/exec" - "strings" - "time" - - "k8s.io/apimachinery/pkg/util/intstr" - - "github.com/kubesmarts/logic-operator/test" - "github.com/kubesmarts/logic-operator/test/utils" - - //nolint:golint - //nolint:revive - . "github.com/onsi/ginkgo/v2" - - //nolint:golint - //nolint:revive - . "github.com/onsi/gomega" -) - -const ( - workflowAppLabel = "sonataflow.org/workflow-app" -) - -var _ = Describe("Workflow Non-Persistence Use Cases :: ", Label("flows-ephemeral"), Ordered, func() { - - var targetNamespace string - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - err := kubectlCreateNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace - if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = kubectlDeleteNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - } - }) - - Describe("Ensure basic workflow deployments", func() { - - It("should successfully deploy the Simple Workflow in GitOps profile and verify if it's running", func() { - By("creating an instance of the SonataFlow Operand(CR)") - sonataFlowCrFile := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow.yaml") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace, prebuiltWorkflows.Greetings.Name, prebuiltWorkflows.Greetings.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(prebuiltWorkflows.Greetings.Name, targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - }) - - It("should successfully deploy the Greeting Workflow in preview profile and verify if it's running", func() { - By("creating external resources DataInputSchema configMap") - EventuallyWithOffset(1, func() error { - cmd := exec.Command("kubectl", "apply", "-f", test.GetPathFromDataDirectory(test.SonataFlowGreetingsDataInputSchemaConfig), "-n", targetNamespace) - _, err := utils.Run(cmd) - return err - }, 3*time.Minute, time.Second).Should(Succeed()) - - sonataFlowYaml := test.GetPathFromDataDirectory(test.SonataFlowGreetingsWithDataInputSchemaCR) - By("creating an instance of the SonataFlow Operand(CR)") - EventuallyWithOffset(1, func() error { - cmd := exec.Command("kubectl", "apply", "-f", sonataFlowYaml, "-n", targetNamespace) - _, err := utils.Run(cmd) - return err - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState("greeting", targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - EventuallyWithOffset(1, func() error { - cmd := exec.Command("kubectl", "delete", "-f", sonataFlowYaml, "-n", targetNamespace) - _, err := utils.Run(cmd) - return err - }, 3*time.Minute, time.Second).Should(Succeed()) - }) - - It("should successfully deploy the orderprocessing workflow in devmode and verify if it's running", func() { - orderProcessingFolder := test.GetPathFromE2EDirectory("order-processing") - By("creating an instance of the SonataFlow Workflow in DevMode") - EventuallyWithOffset(1, func() error { - cmd := exec.Command("kubectl", "apply", "-f", orderProcessingFolder, "-n", targetNamespace) - _, err := utils.Run(cmd) - return err - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState("orderprocessing", targetNamespace) }, 10*time.Minute, 30*time.Second).Should(BeTrue()) - - cmdLog := exec.Command("kubectl", "logs", "orderprocessing", "-n", targetNamespace) - if responseLog, errLog := utils.Run(cmdLog); errLog == nil { - GinkgoWriter.Println(fmt.Sprintf("devmode podlog %s", responseLog)) - } - - By("check that the workflow is addressable") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsAddressable("orderprocessing", targetNamespace) }, 10*time.Minute, 30*time.Second).Should(BeTrue()) - - EventuallyWithOffset(1, func() error { - cmd := exec.Command("kubectl", "delete", "-f", orderProcessingFolder, "-n", targetNamespace) - _, err := utils.Run(cmd) - return err - }, 3*time.Minute, time.Second).Should(Succeed()) - }) - }) -}) - -var _ = Describe("Workflow Persistence Use Cases :: ", Label("flows-persistence"), Ordered, func() { - - const ( - dbConnectionName = "Database connections health check" - defaultDataCheck = "" - ) - var ( - ns string - ) - - BeforeEach(func() { - ns = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - cmd := exec.Command("kubectl", "create", "namespace", ns) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - if len(ns) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", ns, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - cmd = exec.Command("kubectl", "delete", "namespace", ns, "--wait") - _, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - } - - }) - DescribeTable("when deploying a SonataFlow CR with PostgreSQL persistence", func(testcaseDir string, withPersistence bool, waitKSinkInjection bool) { - By("Deploy the CR") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", testcaseDir) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", ns, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - if withPersistence { - return kubectlPatchSonataFlowImageAndRollout(ns, prebuiltWorkflows.CallBackPersistence.Name, prebuiltWorkflows.CallBackPersistence.Tag) - } - return kubectlPatchSonataFlowImageAndRollout(ns, prebuiltWorkflows.CallBack.Name, prebuiltWorkflows.CallBack.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("Wait for SonataFlow CR to complete deployment") - // wait for service deployments to be ready - EventuallyWithOffset(1, func() bool { - cmd = exec.Command("kubectl", "wait", "pod", "-n", ns, "-l", workflowAppLabel, "--for", "condition=Ready", "--timeout=5s") - out, err := utils.Run(cmd) - if err != nil { - return false - } - GinkgoWriter.Printf("%s\n", string(out)) - if !waitKSinkInjection { - return true - } - GinkgoWriter.Println("waitForPodRestartCompletion") - waitForPodRestartCompletion(workflowAppLabel, ns) - GinkgoWriter.Println("waitForPodRestartCompletion done") - return true - }, 5*time.Minute, 5*time.Second).Should(BeTrue()) - - By("Evaluate status of the workflow's pod database connection health endpoint") - cmd = exec.Command("kubectl", "get", "pod", "-l", workflowAppLabel, "-n", ns, "-ojsonpath={.items[*].metadata.name}") - output, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - EventuallyWithOffset(1, func() bool { - for _, pn := range strings.Split(string(output), " ") { - h, err := getHealthFromPod(pn, ns) - if err != nil { - continue - } - Expect(h.Status).To(Equal(upStatus), "Pod health is not UP") - if withPersistence { - connectionCheckFound := false - for _, c := range h.Checks { - if c.Name == dbConnectionName { - Expect(c.Status).To(Equal(upStatus), "Pod's database connection is not UP") - Expect(c.Data[defaultDataCheck]).To(Equal(upStatus), "Pod's 'default' database data is not UP") - connectionCheckFound = true - } - } - Expect(connectionCheckFound).To(Equal(true), "Connection health check not found, but the wofkflow has persistence") - return true - } else { - connectionCheckFound := false - for _, c := range h.Checks { - if c.Name == dbConnectionName { - connectionCheckFound = true - } - } - Expect(connectionCheckFound).To(Equal(false), "Connection health check was found, but the workflow don't have persistence") - return true - } - } - return false - }, 4*time.Minute).Should(BeTrue()) - // Persistence initialization checks - cmd = exec.Command("kubectl", "get", "pod", "-l", workflowAppLabel, "-n", ns, "-ojsonpath={.items[*].metadata.name}") - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - podName := string(output) - cmd = exec.Command("kubectl", "logs", podName, "-n", ns) - output, err = utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - logs := string(output) - if withPersistence { - By("Validate that the workflow persistence was properly initialized") - Expect(logs).Should(ContainSubstring("Flyway Community Edition")) - Expect(logs).Should(ContainSubstring("Database: jdbc:postgresql://postgres.%s:5432", ns)) - result := verifySchemaMigration(logs, prebuiltWorkflows.CallBackPersistence.Name) - GinkgoWriter.Println(fmt.Sprintf("verifySchemaMigration: %v", result)) - Expect(result).Should(BeTrue()) - Expect(logs).Should(ContainSubstring("Profile prod activated")) - } else { - By("Validate that the workflow has no persistence") - Expect(logs).ShouldNot(ContainSubstring("Flyway Community Edition")) - Expect(logs).ShouldNot(ContainSubstring(fmt.Sprintf(`Creating schema "%s"`, prebuiltWorkflows.CallBack.Name))) - Expect(logs).Should(ContainSubstring("Profile prod activated")) - } - }, - Entry("defined in the workflow from an existing kubernetes service as a reference", test.GetPathFromE2EDirectory("workflows", "persistence", "by_service"), true, false), - Entry("defined in the workflow and from the sonataflow platform", test.GetPathFromE2EDirectory("workflows", "persistence", "from_platform_overwritten_by_service"), true, false), - Entry("defined from the sonataflow platform as reference and with DI and JS", test.GetPathFromE2EDirectory("workflows", "persistence", "from_platform_with_di_and_js_services"), true, true), - Entry("defined from the sonataflow platform as reference and without DI and JS", test.GetPathFromE2EDirectory("workflows", "persistence", "from_platform_without_di_and_js_services"), true, false), - Entry("defined from the sonataflow platform as reference but not required by the workflow", test.GetPathFromE2EDirectory("workflows", "persistence", "from_platform_with_no_persistence_required"), false, false), - ) -}) - -var _ = Describe("Workflow Monitoring Use Cases :: ", Label("flows-monitoring"), Ordered, func() { - - var targetNamespace string - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - err := kubectlCreateNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace - if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = kubectlDeleteNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - } - }) - Describe("basic workflow monitoring", func() { - It("should create servicemonitor for workflow deployed as k8s deployment when monitoring enabled in platform", func() { - By("Deploy the SonataFlowPlatform CR and the workflow") - var manifests []byte - EventuallyWithOffset(1, func() error { - var err error - cmd := exec.Command("kubectl", "kustomize", test.GetPathFromE2EDirectory("workflows", "prometheus", "k8s_deployment")) - manifests, err = utils.Run(cmd) - return err - }, time.Minute, time.Second).Should(Succeed()) - cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") - cmd.Stdin = bytes.NewBuffer(manifests) - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - - workflowName := prebuiltWorkflows.Greetings.Name - By("Replacing the image with a prebuilt one and rollout") - EventuallyWithOffset(1, func() error { - return kubectlPatchSonataFlowImageAndRollout(targetNamespace, workflowName, prebuiltWorkflows.Greetings.Tag) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(workflowName, targetNamespace) }, 10*time.Minute, 30*time.Second).Should(BeTrue()) - - By("Retrieve the name of the running pod for the workflow") - labels := fmt.Sprintf("sonataflow.org/workflow-app=%s,sonataflow.org/workflow-namespace=%s", workflowName, targetNamespace) - podName := waitForPodRestartCompletion(labels, targetNamespace) - - By("check service monitor has been created") - EventuallyWithOffset(1, func() bool { - cmd := exec.Command("kubectl", "get", "servicemonitor", workflowName, "-n", targetNamespace) - _, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get servicemonitor: %v", err)) - return false - } - return true - }, 1*time.Minute, 5).Should(BeTrue()) - - By("trigger a new workflow instance") - EventuallyWithOffset(1, func() bool { - curlCmd := fmt.Sprintf("curl -X POST -H 'Content-Type: application/json' -H 'Accept: */*' -d '{\"workflowdata\": {}}' http://%s/%s", workflowName, workflowName) - cmd := exec.Command("kubectl", "exec", podName, "-c", "workflow", "-n", targetNamespace, "--", "/bin/bash", "-c", curlCmd) - resp, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to trigger workflow instance: %v", err)) - return false - } - GinkgoWriter.Println(fmt.Errorf("Response: %v", string(resp))) - return strings.Contains(string(resp), "Hello World") - }, 2*time.Minute, 5).Should(BeTrue()) - - By("check prometheus server has workflow instance metrics") - EventuallyWithOffset(1, func() bool { - curlCmd := fmt.Sprintf("curl http://prometheus-operated.default:9090/api/v1/query --data-urlencode 'query=kogito_process_instance_duration_seconds_count{job=\"%s\",namespace=\"%s\"}'", workflowName, targetNamespace) - GinkgoWriter.Println(curlCmd) - cmd := exec.Command("kubectl", "exec", podName, "-c", "workflow", "-n", targetNamespace, "--", "/bin/bash", "-c", curlCmd) - resp, err := utils.Run(cmd) - if err != nil { - GinkgoWriter.Println(fmt.Errorf("failed to get metrics from prometheus server: %v", err)) - return false - } - if val, err := getMetricValue(string(resp)); err != nil { - GinkgoWriter.Println(err) - return false - } else { - GinkgoWriter.Println("metric value found:", val) - return val == "1" - } - }, 5*time.Minute, 5).Should(BeTrue()) - }) - }) -}) - -var _ = Describe("Workflow HorizontalPodAutoscaling Use Cases :: ", Label("flows-hpa"), Ordered, func() { - var targetNamespace string - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - err := kubectlCreateNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace - if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = kubectlDeleteNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - } - }) - - Describe("Ensure HPA works by workflow profile", func() { - - It("HPA should work for the greetings workflow in GitOps profile.", func() { - - By("deploy the workflow with gitops profile") - sonataFlowCrFileTemplate := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow.yaml") - sonataFlowCrFile := createTmpCopy(sonataFlowCrFileTemplate) - GinkgoWriter.Println(fmt.Sprintf("configuring image and replicas in sonataflowCrFile: %s", sonataFlowCrFile)) - setImageAndReplicasOrFail(sonataFlowCrFile, prebuiltWorkflows.Greetings.Tag, int32(1)) - - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(prebuiltWorkflows.Greetings.Name, targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow has 1 replica") - - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(1)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("create the HPA to manage the workflow replicas") - sonataFlowCrFileHPA := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml") - - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check that the workflow has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow scale subresource .spec.replicas is 3 after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowScaleSubresourceReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow scale subresource .status.replicas is 3 after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowScaleSubresourceStatusReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow associated deployment has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - }) - - It("HPA should work for the greetings workflow in Preview profile.", func() { - - By("deploy the workflow with preview profile") - sonataFlowCrFileTemplate := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow.yaml") - sonataFlowCrFile := createTmpCopy(sonataFlowCrFileTemplate) - GinkgoWriter.Println(fmt.Sprintf("configuring image and replicas in sonataflowCrFile: %s", sonataFlowCrFile)) - setImageAndReplicasOrFail(sonataFlowCrFile, "", int32(1)) - setProfileOrFail(sonataFlowCrFile, "preview") - - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(prebuiltWorkflows.Greetings.Name, targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that workflow has 1 replica") - - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(1)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("create the HPA to manage the workflow replicas") - sonataFlowCrFileHPA := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml") - - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check that the workflow has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow scale subresource .spec.replicas is 3 after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowScaleSubresourceReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow scale subresource .status.replicas is 3 after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowScaleSubresourceStatusReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow associated deployment has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyDeploymentReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - }) - }) -}) - -var _ = Describe("Workflow PodDisruptionBudget Use Cases :: ", Label("flows-pdb"), Ordered, func() { - var targetNamespace string - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - err := kubectlCreateNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace - if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = kubectlDeleteNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - } - }) - - DescribeTable("Ensure PDB works by workflow profile", func(profile string, usePercent bool) { - - By("create the template file") - sonataFlowCrFileTemplate := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow.yaml") - sonataFlowCrFile := createTmpCopy(sonataFlowCrFileTemplate) - - if profile == "gitops" { - By("setup the workflow file for the gitops profile") - setImageAndReplicasOrFail(sonataFlowCrFile, prebuiltWorkflows.Greetings.Tag, int32(4)) - setProfileOrFail(sonataFlowCrFile, "gitops") - } else { - By("setup the workflow file for the preview profile") - setImageAndReplicasOrFail(sonataFlowCrFile, "", int32(4)) - setProfileOrFail(sonataFlowCrFile, "preview") - } - - var minReplicas intstr.IntOrString - if usePercent { - By("setup the workflow podDisruptionBudget using 50% minReplicas") - minReplicas = intstr.FromString("50%") - } else { - By("setup the workflow podDisruptionBudget using 2 minReplicas") - minReplicas = intstr.FromInt32(int32(2)) - } - setPodDisruptionBudgetOrFail(sonataFlowCrFile, &minReplicas, nil) - - By("deploy the workflow") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(prebuiltWorkflows.Greetings.Name, targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow has 4 replica") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(4)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget was created") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(prebuiltWorkflows.Greetings.Name, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget's DisruptionAllowed condition is True") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(prebuiltWorkflows.Greetings.Name, targetNamespace, "DisruptionAllowed", "True") - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is allowing 2 disruptions") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(2)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("scale the workflow to 1") - setReplicasOrFail(sonataFlowCrFile, int32(1)) - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check that the workflow has 1 replica") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(1)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is removed after scaling the workflow to 1") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(prebuiltWorkflows.Greetings.Name, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeFalse()) - }, - Entry("Workflow with gitops profile and disruption budget with minReplicas: 50%", "gitops", true), - Entry("Workflow with gitops profile and disruption budget with minReplicas: 2", "gitops", false), - Entry("Workflow with preview profile and disruption budget with minReplicas: 50%", "preview", true), - Entry("Workflow with preview profile and disruption budget with minReplicas: 2", "preview", false), - ) -}) - -var _ = Describe("Workflow PodDisruptionBudget + HorizontalPodAutoscaler Use Cases :: ", Label("flows-pdb-with-hpa"), Ordered, func() { - var targetNamespace string - BeforeEach(func() { - targetNamespace = fmt.Sprintf("test-%d", rand.Intn(randomIntRange)+1) - err := kubectlCreateNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - }) - AfterEach(func() { - // Remove resources in test namespace - if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { - cmd := exec.Command("kubectl", "delete", "sonataflow", "--all", "-n", targetNamespace, "--wait") - _, err := utils.Run(cmd) - Expect(err).NotTo(HaveOccurred()) - err = kubectlDeleteNamespace(targetNamespace) - Expect(err).NotTo(HaveOccurred()) - } - }) - - DescribeTable("Ensure PDB works by workflow profile when using a HPA", func(profile string, usePercent bool) { - - By("create the template file") - sonataFlowCrFileTemplate := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow.yaml") - sonataFlowCrFile := createTmpCopy(sonataFlowCrFileTemplate) - - if profile == "gitops" { - By("setup the workflow file for the gitops profile and 1 replica") - setImageAndReplicasOrFail(sonataFlowCrFile, prebuiltWorkflows.Greetings.Tag, int32(1)) - setProfileOrFail(sonataFlowCrFile, "gitops") - } else { - By("setup the workflow file for the preview profile and 1 replica") - setImageAndReplicasOrFail(sonataFlowCrFile, "", int32(1)) - setProfileOrFail(sonataFlowCrFile, "preview") - } - - var minReplicas intstr.IntOrString - if usePercent { - By("setup the workflow podDisruptionBudget using 30% minReplicas") - minReplicas = intstr.FromString("30%") - } else { - By("setup the workflow podDisruptionBudget using 1 minReplicas") - minReplicas = intstr.FromInt32(int32(1)) - } - setPodDisruptionBudgetOrFail(sonataFlowCrFile, &minReplicas, nil) - - By("deploy the workflow") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check the workflow is in running state") - EventuallyWithOffset(1, func() bool { return verifyWorkflowIsInRunningState(prebuiltWorkflows.Greetings.Name, targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the workflow has 1 replica") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(1)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that no PodDisruptionBudget was created since the workflow has 1 replica") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(prebuiltWorkflows.Greetings.Name, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeFalse()) - - By("create the HPA to manage the workflow replicas and configured to ensure 3 min replicas") - sonataFlowCrFileHPA := test.GetPathFromE2EDirectory("workflows", prebuiltWorkflows.Greetings.Name, "01-sonataflow.org_v1alpha08_sonataflow_hpa.yaml") - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check that the workflow has 3 replicas after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(3)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget was created after creating the HPA") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(prebuiltWorkflows.Greetings.Name, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget's DisruptionAllowed condition is True") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetConditionHasStatus(prebuiltWorkflows.Greetings.Name, targetNamespace, "DisruptionAllowed", "True") - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is allowing 2 disruptions") - EventuallyWithOffset(1, func() bool { - return verifyPodDisruptionBudgetAllowsDisruptionNumber(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(2)) - }, 3*time.Minute, 30*time.Second).Should(BeTrue()) - - By("delete the HPA") - EventuallyWithOffset(1, func() error { - return kubectlDeleteFileOnCluster(sonataFlowCrFileHPA, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("scale the workflow to 1") - setReplicasOrFail(sonataFlowCrFile, int32(1)) - EventuallyWithOffset(1, func() error { - return kubectlApplyFileOnCluster(sonataFlowCrFile, targetNamespace) - }, 3*time.Minute, time.Second).Should(Succeed()) - - By("check that the workflow has 1 replica") - EventuallyWithOffset(1, func() bool { - return verifyWorkflowReplicas(prebuiltWorkflows.Greetings.Name, targetNamespace, int32(1)) - }, 2*time.Minute, 30*time.Second).Should(BeTrue()) - - By("check that the PodDisruptionBudget is removed after scaling the workflow to 1") - EventuallyWithOffset(1, func() bool { - return verifyResourceExists(prebuiltWorkflows.Greetings.Name, "pdb", targetNamespace) - }, 3*time.Minute, 30*time.Second).Should(BeFalse()) - - }, - Entry("Workflow with gitops profile and disruption budget with minReplicas: 30%", "gitops", true), - Entry("Workflow with gitops profile and disruption budget with minReplicas: 1", "gitops", false), - Entry("Workflow with preview profile and disruption budget with minReplicas: 30%", "preview", true), - Entry("Workflow with preview profile and disruption budget with minReplicas: 1", "preview", false), - ) -}) diff --git a/test/kubernetes_cli.go b/test/kubernetes_cli.go deleted file mode 100644 index c7f9bc66..00000000 --- a/test/kubernetes_cli.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 test - -import ( - "context" - - "testing" - - prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - "github.com/kubesmarts/logic-operator/utils" - - buildv1 "github.com/openshift/api/build/v1" - imgv1 "github.com/openshift/api/image/v1" - routev1 "github.com/openshift/api/route/v1" - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/tools/record" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func NewFakeRecorder() record.EventRecorder { - return record.NewFakeRecorder(10) -} - -type SonataFlowClientBuilder struct { - innerBuilder *fake.ClientBuilder -} - -// Build from the underlying fake.ClientBuilder. -// To overwrite this method we need to forward all the functions from the -// base implementation since they do not use an interface. -func (s *SonataFlowClientBuilder) Build() ctrl.WithWatch { - cli := s.innerBuilder.Build() - utils.SetClient(cli) - return cli -} - -func (s *SonataFlowClientBuilder) WithRuntimeObjects(initRuntimeObjs ...runtime.Object) *SonataFlowClientBuilder { - _ = s.innerBuilder.WithRuntimeObjects(initRuntimeObjs...) - return s -} - -func (s *SonataFlowClientBuilder) WithStatusSubresource(o ...ctrl.Object) *SonataFlowClientBuilder { - _ = s.innerBuilder.WithStatusSubresource(o...) - return s -} - -// NewSonataFlowClientBuilder creates a new fake.ClientBuilder with the right scheme references -func NewSonataFlowClientBuilder() *SonataFlowClientBuilder { - s := scheme.Scheme - utilruntime.Must(operatorapi.AddToScheme(s)) - builder := fake.NewClientBuilder().WithScheme(s) - return &SonataFlowClientBuilder{ - innerBuilder: builder, - } -} - -func NewSonataFlowClientBuilderWithKnative() *SonataFlowClientBuilder { - s := scheme.Scheme - utilruntime.Must(operatorapi.AddToScheme(s)) - utilruntime.Must(servingv1.AddToScheme(s)) - builder := fake.NewClientBuilder().WithScheme(s) - return &SonataFlowClientBuilder{ - innerBuilder: builder, - } -} - -// NewKogitoClientBuilderWithOpenShift creates a new fake client with OpenShift schemas. -// If your object is not present, just add in the list below. -func NewKogitoClientBuilderWithOpenShift() *SonataFlowClientBuilder { - s := scheme.Scheme - utilruntime.Must(routev1.Install(s)) - utilruntime.Must(buildv1.Install(s)) - utilruntime.Must(imgv1.Install(s)) - utilruntime.Must(operatorapi.AddToScheme(s)) - utilruntime.Must(eventingv1.AddToScheme(s)) - utilruntime.Must(sourcesv1.AddToScheme(s)) - utilruntime.Must(prometheus.AddToScheme(s)) - builder := fake.NewClientBuilder().WithScheme(s) - return &SonataFlowClientBuilder{ - innerBuilder: builder, - } -} - -func MustGetDeployment(t *testing.T, client ctrl.WithWatch, workflow *operatorapi.SonataFlow) *appsv1.Deployment { - deployment := &appsv1.Deployment{} - return mustGet(t, client, workflow, deployment).(*appsv1.Deployment) -} - -func MustGetService(t *testing.T, client ctrl.WithWatch, workflow *operatorapi.SonataFlow) *v1.Service { - svc := &v1.Service{} - return mustGet(t, client, workflow, svc).(*v1.Service) -} - -func MustGetConfigMap(t *testing.T, client ctrl.WithWatch, workflow *operatorapi.SonataFlow) *v1.ConfigMap { - cm := &v1.ConfigMap{} - return mustGet(t, client, workflow, cm).(*v1.ConfigMap) -} - -func MustGetWorkflow(t *testing.T, client ctrl.WithWatch, name types.NamespacedName) *operatorapi.SonataFlow { - workflow := &operatorapi.SonataFlow{} - workflow.Name = name.Name - workflow.Namespace = name.Namespace - return mustGet(t, client, workflow, workflow).(*operatorapi.SonataFlow) -} - -func MustGetBuild(t *testing.T, client ctrl.WithWatch, name types.NamespacedName) *operatorapi.SonataFlowBuild { - build := &operatorapi.SonataFlowBuild{} - err := client.Get(context.TODO(), name, build) - assert.NoError(t, err) - return build -} - -func mustGet(t *testing.T, client ctrl.WithWatch, workflow *operatorapi.SonataFlow, obj ctrl.Object) ctrl.Object { - err := client.Get(context.TODO(), ctrl.ObjectKeyFromObject(workflow), obj) - assert.NoError(t, err) - return obj -} diff --git a/test/mock_service.go b/test/mock_service.go deleted file mode 100644 index 2003c5d6..00000000 --- a/test/mock_service.go +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 test - -import ( - "context" - - oappsv1 "github.com/openshift/api/apps/v1" - buildv1 "github.com/openshift/api/build/v1" - consolev1 "github.com/openshift/api/console/v1" - oimagev1 "github.com/openshift/api/image/v1" - routev1 "github.com/openshift/api/route/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - clientv1 "sigs.k8s.io/controller-runtime/pkg/client" -) - -type MockPlatformService struct { - Client clientv1.Client - scheme *runtime.Scheme - CreateFunc func(ctx context.Context, obj clientv1.Object, opts ...clientv1.CreateOption) error - DeleteFunc func(ctx context.Context, obj clientv1.Object, opts ...clientv1.DeleteOption) error - GetFunc func(ctx context.Context, key clientv1.ObjectKey, obj clientv1.Object) error - ListFunc func(ctx context.Context, list clientv1.ObjectList, opts ...clientv1.ListOption) error - UpdateFunc func(ctx context.Context, obj clientv1.Object, opts ...clientv1.UpdateOption) error - PatchFunc func(ctx context.Context, obj clientv1.Object, patch clientv1.Patch, opts ...clientv1.PatchOption) error - DeleteAllOfFunc func(ctx context.Context, obj clientv1.Object, opts ...clientv1.DeleteAllOfOption) error - GetCachedFunc func(ctx context.Context, key clientv1.ObjectKey, obj clientv1.Object) error - GetSchemeFunc func() *runtime.Scheme - StatusFunc func() clientv1.StatusWriter -} - -var knownTypes = map[schema.GroupVersion][]runtime.Object{ - corev1.SchemeGroupVersion: { - &corev1.PersistentVolumeClaim{}, - &corev1.ServiceAccount{}, - &corev1.Secret{}, - &corev1.Service{}, - &corev1.ServiceList{}, - &corev1.PersistentVolumeClaimList{}, - &corev1.ServiceAccountList{}, - &corev1.ConfigMap{}, - &corev1.ConfigMapList{}, - }, - oappsv1.GroupVersion: { - &oappsv1.DeploymentConfig{}, - &oappsv1.DeploymentConfigList{}, - }, - appsv1.SchemeGroupVersion: { - &appsv1.StatefulSet{}, - &appsv1.StatefulSetList{}, - }, - routev1.GroupVersion: { - &routev1.Route{}, - &routev1.RouteList{}, - }, - oimagev1.GroupVersion: { - &oimagev1.ImageStream{}, - &oimagev1.ImageStreamList{}, - }, - rbacv1.SchemeGroupVersion: { - &rbacv1.Role{}, - &rbacv1.RoleList{}, - &rbacv1.RoleBinding{}, - &rbacv1.RoleBindingList{}, - }, - buildv1.GroupVersion: { - &buildv1.BuildConfig{}, - &buildv1.BuildConfigList{}, - }, - consolev1.GroupVersion: { - &consolev1.ConsoleLink{}, - &consolev1.ConsoleLinkList{}, - &consolev1.ConsoleYAMLSample{}, - &consolev1.ConsoleYAMLSampleList{}, - }, -} - -func (service *MockPlatformService) Create(ctx context.Context, obj clientv1.Object, opts ...clientv1.CreateOption) error { - return service.CreateFunc(ctx, obj, opts...) -} - -func (service *MockPlatformService) Delete(ctx context.Context, obj clientv1.Object, opts ...clientv1.DeleteOption) error { - return service.DeleteFunc(ctx, obj, opts...) -} - -func (service *MockPlatformService) Get(ctx context.Context, key clientv1.ObjectKey, obj clientv1.Object) error { - return service.GetFunc(ctx, key, obj) -} - -func (service *MockPlatformService) List(ctx context.Context, list clientv1.ObjectList, opts ...clientv1.ListOption) error { - return service.ListFunc(ctx, list, opts...) -} - -func (service *MockPlatformService) Update(ctx context.Context, obj clientv1.Object, opts ...clientv1.UpdateOption) error { - return service.UpdateFunc(ctx, obj, opts...) -} - -func (service *MockPlatformService) Patch(ctx context.Context, obj clientv1.Object, patch clientv1.Patch, opts ...clientv1.PatchOption) error { - return service.PatchFunc(ctx, obj, patch, opts...) -} - -func (service *MockPlatformService) DeleteAllOf(ctx context.Context, obj clientv1.Object, opts ...clientv1.DeleteAllOfOption) error { - return service.DeleteAllOfFunc(ctx, obj, opts...) -} - -func (service *MockPlatformService) GetCached(ctx context.Context, key clientv1.ObjectKey, obj clientv1.Object) error { - return service.GetCachedFunc(ctx, key, obj) -} - -func (service *MockPlatformService) GetScheme() *runtime.Scheme { - return service.GetSchemeFunc() -} - -func (service *MockPlatformService) Status() clientv1.StatusWriter { - return service.StatusFunc() -} - -func (service *MockPlatformService) IsMockService() bool { - return true -} diff --git a/test/testdata/db_migrator_sonataflow_platform.yaml b/test/testdata/db_migrator_sonataflow_platform.yaml deleted file mode 100644 index 20cb5055..00000000 --- a/test/testdata/db_migrator_sonataflow_platform.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: db-migration-sonataflow-platform -spec: - build: - config: - strategyOptions: - KanikoBuildCacheEnabled: "true" - services: - dataIndex: - enabled: true - persistence: - dbMigrationStrategy: job - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD - jobService: - enabled: true - persistence: - dbMigrationStrategy: job - postgresql: - jdbcUrl: jdbc:postgresql://postgres:5432/sonataflow?currentSchema=jobs-service - secretRef: - name: postgres-secrets - userKey: POSTGRES_USER - passwordKey: POSTGRES_PASSWORD diff --git a/test/testdata/grafana.yaml b/test/testdata/grafana.yaml deleted file mode 100644 index a0d24404..00000000 --- a/test/testdata/grafana.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -apiVersion: grafana.integreatly.org/v1beta1 -kind: Grafana -metadata: - name: grafana - labels: - dashboards: "grafana" -spec: - config: - security: - admin_user: root - admin_password: secret diff --git a/test/testdata/knative_default_broker.yaml b/test/testdata/knative_default_broker.yaml deleted file mode 100644 index 7a0f5951..00000000 --- a/test/testdata/knative_default_broker.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: eventing.knative.dev/v1 -kind: Broker -metadata: - annotations: - eventing.knative.dev/broker.class: MTChannelBasedBroker - name: default -spec: - config: - apiVersion: v1 - kind: ConfigMap - name: config-br-default-channel - namespace: knative-eventing - delivery: - backoffDelay: PT0.2S - backoffPolicy: exponential - retry: 10 -status: - address: - name: http - url: http://broker-ingress.knative-eventing.svc.cluster.local/sonataflow-infra/default - annotations: - knative.dev/channelAPIVersion: messaging.knative.dev/v1 - knative.dev/channelAddress: http://default-kne-trigger-kn-channel.sonataflow-infra.svc.cluster.local - knative.dev/channelKind: InMemoryChannel - knative.dev/channelName: default-kne-trigger - conditions: - - lastTransitionTime: "2024-07-16T18:58:35Z" - status: "True" - type: Addressable - - lastTransitionTime: "2024-07-16T18:58:35Z" - message: No dead letter sink is configured. - reason: DeadLetterSinkNotConfigured - severity: Info - status: "True" - type: DeadLetterSinkResolved - - lastTransitionTime: "2024-07-16T18:58:35Z" - status: "True" - type: FilterReady - - lastTransitionTime: "2024-07-16T18:58:35Z" - status: "True" - type: IngressReady - - lastTransitionTime: "2024-07-16T18:58:35Z" - status: "True" - type: Ready - - lastTransitionTime: "2024-07-16T18:58:35Z" - status: "True" - type: TriggerChannelReady - observedGeneration: 1 diff --git a/test/testdata/knative_serving_eventing.yaml b/test/testdata/knative_serving_eventing.yaml deleted file mode 100644 index 23a06f96..00000000 --- a/test/testdata/knative_serving_eventing.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: v1 -kind: Namespace -metadata: - name: knative-serving ---- -apiVersion: operator.knative.dev/v1beta1 -kind: KnativeServing -metadata: - name: knative-serving - namespace: knative-serving -spec: - ingress: - kourier: - enabled: true - config: - network: - ingress-class: "kourier.ingress.networking.knative.dev" ---- -apiVersion: v1 -kind: Namespace -metadata: - name: knative-eventing ---- -apiVersion: operator.knative.dev/v1beta1 -kind: KnativeEventing -metadata: - name: knative-eventing - namespace: knative-eventing diff --git a/test/testdata/prometheus.yaml b/test/testdata/prometheus.yaml deleted file mode 100644 index e15778ce..00000000 --- a/test/testdata/prometheus.yaml +++ /dev/null @@ -1,72 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: monitoring.coreos.com/v1 -kind: Prometheus -metadata: - name: prometheus -spec: - serviceAccountName: prometheus - serviceMonitorNamespaceSelector: {} - serviceMonitorSelector: {} - podMonitorSelector: {} - resources: - requests: - memory: 400Mi ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: prometheus ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: prometheus -rules: - - apiGroups: [""] - resources: - - nodes - - nodes/metrics - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: - - configmaps - verbs: ["get"] - - apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: ["get", "list", "watch"] - - nonResourceURLs: ["/metrics"] - verbs: ["get"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: prometheus -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: prometheus -subjects: - - kind: ServiceAccount - name: prometheus - namespace: default diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml deleted file mode 100644 index 298489f0..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: dev -spec: - resources: - configMaps: - - configMap: - name: greetings-staticfiles - workflowPath: META-INF/resources - flow: - start: ChooseOnLanguage - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml deleted file mode 100644 index 3d3f0d95..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: simple - annotations: - sonataflow.org/description: Simple example on k8s! - sonataflow.org/version: 0.0.1 - labels: - test: test -spec: - podTemplate: - container: - image: my/image/test:latest - flow: - start: HelloWorld - states: - - name: HelloWorld - type: inject - data: - message: Hello World - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml deleted file mode 100644 index 57c3387f..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 - labels: - test: test -spec: - flow: - start: ChooseOnLanguage - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml deleted file mode 100644 index 591163fe..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 - sonataflow.org/profile: dev -spec: - flow: - start: ChooseOnLanguage - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml deleted file mode 100644 index 0813a0a1..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: eventtest - annotations: - sonataflow.org/description: An example of how to consume events over HTTP - sonataflow.org/version: 1.0.0 - sonataflow.org/expressionLang: jsonpath - sonataflow.org/profile: dev -spec: - flow: - start: printWaitMessage - events: - - name: startEvent - source: "" - type: start - - name: moveEvent - source: "" - type: move - functions: - - name: printMessage - type: custom - operation: sysout - states: - - name: printWaitMessage - type: event - onEvents: - - eventRefs: - - startEvent - actions: - - name: printAfterStart - functionRef: - refName: printMessage - arguments: - message: "$[*]" - transition: waitForEvent - - name: waitForEvent - type: event - onEvents: - - eventRefs: - - moveEvent - actions: - - name: printAfterEvent - functionRef: - refName: printMessage - arguments: - message: "$[*]" - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml deleted file mode 100644 index 7bc4c925..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml +++ /dev/null @@ -1,66 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: greeting - annotations: - sonataflow.org/description: Greeting example on k8s! - sonataflow.org/version: 0.0.1 -spec: - resources: - configMaps: - - configMap: - name: greetings-input-schema - flow: - start: ChooseOnLanguage - dataInputSchema: - schema: input.json - failOnValidationErrors: true - functions: - - name: greetFunction - type: custom - operation: sysout - states: - - name: ChooseOnLanguage - type: switch - dataConditions: - - condition: '${ .language == "English" }' - transition: GreetInEnglish - - condition: '${ .language == "Spanish" }' - transition: GreetInSpanish - defaultCondition: GreetInEnglish - - name: GreetInEnglish - type: inject - data: - greeting: "Hello from JSON Workflow, " - transition: GreetPerson - - name: GreetInSpanish - type: inject - data: - greeting: "Saludos desde JSON Workflow, " - transition: GreetPerson - - name: GreetPerson - type: operation - actions: - - name: greetAction - functionRef: - refName: greetFunction - arguments: - message: ".greeting+.name" - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml deleted file mode 100644 index 8636feb0..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml +++ /dev/null @@ -1,85 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlow -metadata: - name: vet - annotations: - sonataflow.org/description: Vet service call via events - sonataflow.org/version: 0.0.1 -spec: - sink: - ref: - name: default - namespace: default - apiVersion: eventing.knative.dev/v1 - kind: Broker - sources: - - eventType: events.vet.appointments - ref: - name: broker-appointments - namespace: default - apiVersion: eventing.knative.dev/v1 - kind: Broker - - eventType: events.vet.appointments.request - ref: - name: broker-appointments-request - namespace: default - apiVersion: eventing.knative.dev/v1 - kind: Broker - flow: - events: - - name: MakeVetAppointment - source: VetServiceSource - type: events.vet.appointments - kind: produced - - name: VetAppointmentInfo - source: VetServiceSource - type: events.vet.appointments - - name: VetAppointmentRequestReceived - source: checkAccountInfo - type: events.vet.appointments.request - functions: - - name: StoreNewPatientInfo - operation: specs/services.yaml#checkAccountInfo - states: - - name: AppointmentRequestReceived - type: event - onEvents: - - eventRefs: - - VetAppointmentRequestReceived - actions: - - name: checkAccount - functionRef: - refName: checkAccountInfo - arguments: - account: "${ .accountId }" - transition: MakeVetAppointmentState - - name: MakeVetAppointmentState - type: callback - action: - name: MakeAppointmentAction - eventRef: - triggerEventRef: MakeVetAppointment - data: "${ .patientInfo }" - eventRef: VetAppointmentInfo - timeouts: - stateExecTimeout: PT15M - eventDataFilter: - toStateData: .test - end: true diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml deleted file mode 100644 index bd07aba6..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowBuild -metadata: - name: greeting -spec: - resources: {} - timeout: 0s -status: - buildPhase: Succeeded - imageTag: host/namespace/image:latest - innerBuild: - metadata: - name: greeting - spec: - strategy: pod - tasks: - - kaniko: - cache: {} - contextDir: /builder/greeting/context - image: greeting:0.0.1 - name: KanikoTask - registry: - address: 10.100.163.129 - resources: {} - timeout: 5m0s - status: - duration: 2m49s - phase: Succeeded - repositoryImageTag: 10.100.163.129/greeting:0.0.1 - resourceVolume: - referenceName: sonataflow-greeting-builder - referenceType: configMap - startedAt: "2023-08-03T16:11:47Z" diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml deleted file mode 100644 index 57e9735d..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowClusterPlatform -metadata: - name: cluster -spec: - platformRef: - name: sonataflow-platform - namespace: test-ns diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml deleted file mode 100644 index 93498cd0..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - properties: - flow: - - name: quarkus.log.level - value: INFO - build: - config: - strategy: operator - registry: - address: host/namespace - secret: regcred diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml deleted file mode 100644 index d0add9fb..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - build: - config: - strategy: platform diff --git a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withBroker.yaml b/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withBroker.yaml deleted file mode 100644 index 73688a31..00000000 --- a/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withBroker.yaml +++ /dev/null @@ -1,49 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -apiVersion: sonataflow.org/v1alpha08 -kind: SonataFlowPlatform -metadata: - name: sonataflow-platform -spec: - properties: - flow: - - name: quarkus.log.level - value: INFO - build: - config: - strategy: operator - registry: - address: host/namespace - secret: regcred - eventing: - broker: - ref: - name: default - apiVersion: eventing.knative.dev/v1 - kind: Broker - services: - dataIndex: - enabled: true - podTemplate: - container: - resources: {} - jobService: - enabled: true - podTemplate: - container: - resources: {} diff --git a/test/testdata/v1_configmap_greetings_datainput.yaml b/test/testdata/v1_configmap_greetings_datainput.yaml deleted file mode 100644 index b11f0c4f..00000000 --- a/test/testdata/v1_configmap_greetings_datainput.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ConfigMap -apiVersion: v1 -metadata: - name: greetings-input-schema -data: - input.json: |- - { - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "language", - "name" - ] - } diff --git a/test/testdata/v1_configmap_greetings_staticfiles.yaml b/test/testdata/v1_configmap_greetings_staticfiles.yaml deleted file mode 100644 index 6afd93ae..00000000 --- a/test/testdata/v1_configmap_greetings_staticfiles.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -kind: ConfigMap -apiVersion: v1 -metadata: - name: greetings-staticfiles -data: - index.html: |- - - Greetings! - Greetings stranger! - diff --git a/test/utils/utils.go b/test/utils/utils.go index 90e7dfec..448055b5 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -1,79 +1,180 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 utils import ( "bufio" + "bytes" "fmt" "os" "os/exec" - "strconv" "strings" - . "github.com/onsi/ginkgo/v2" //nolint:golint,revive + . "github.com/onsi/ginkgo/v2" // nolint:revive,staticcheck ) -func warnError(err error) { - fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) -} +const ( + prometheusOperatorVersion = "v0.77.1" + prometheusOperatorURL = "https://github.com/prometheus-operator/prometheus-operator/" + + "releases/download/%s/bundle.yaml" -func OutputAllPods() error { - cmd := exec.Command("kubectl", "get", "pods", "-A") - podsOutput, err := Run(cmd) - fmt.Println(string(podsOutput)) - return err -} - -func OutputAllEvents(namespace string) error { - cmd := exec.Command("kubectl", "get", "events", "-n", namespace) - podsOutput, err := Run(cmd) - fmt.Println(string(podsOutput)) - return err -} + certmanagerVersion = "v1.16.3" + certmanagerURLTmpl = "https://github.com/cert-manager/cert-manager/releases/download/%s/cert-manager.yaml" +) -func OutputDeployment(namespace, deployName string) error { - cmd := exec.Command("kubectl", "get", "deploy", deployName, "-o", "yaml", "-n", namespace) - podsOutput, err := Run(cmd) - fmt.Println(string(podsOutput)) - return err +func warnError(err error) { + _, _ = fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir - // To allow make commands be executed from the project directory which is subdir on SDK repo - // TODO:(user) You might does not need the following code if err := os.Chdir(cmd.Dir); err != nil { - GinkgoWriter.Printf("chdir dir: %s\n", err) + _, _ = fmt.Fprintf(GinkgoWriter, "chdir dir: %q\n", err) } cmd.Env = append(os.Environ(), "GO111MODULE=on") command := strings.Join(cmd.Args, " ") + _, _ = fmt.Fprintf(GinkgoWriter, "running: %q\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%q failed with error %q: %w", command, string(output), err) + } + + return string(output), nil +} + +// InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. +func InstallPrometheusOperator() error { + url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion) + cmd := exec.Command("kubectl", "create", "-f", url) + _, err := Run(cmd) + return err +} + +// UninstallPrometheusOperator uninstalls the prometheus +func UninstallPrometheusOperator() { + url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion) + cmd := exec.Command("kubectl", "delete", "-f", url) + if _, err := Run(cmd); err != nil { + warnError(err) + } +} + +// IsPrometheusCRDsInstalled checks if any Prometheus CRDs are installed +// by verifying the existence of key CRDs related to Prometheus. +func IsPrometheusCRDsInstalled() bool { + // List of common Prometheus CRDs + prometheusCRDs := []string{ + "prometheuses.monitoring.coreos.com", + "prometheusrules.monitoring.coreos.com", + "prometheusagents.monitoring.coreos.com", + } + + cmd := exec.Command("kubectl", "get", "crds", "-o", "custom-columns=NAME:.metadata.name") + output, err := Run(cmd) + if err != nil { + return false + } + crdList := GetNonEmptyLines(output) + for _, crd := range prometheusCRDs { + for _, line := range crdList { + if strings.Contains(line, crd) { + return true + } + } + } + + return false +} + +// UninstallCertManager uninstalls the cert manager +func UninstallCertManager() { + url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion) + cmd := exec.Command("kubectl", "delete", "-f", url) + if _, err := Run(cmd); err != nil { + warnError(err) + } +} + +// InstallCertManager installs the cert manager bundle. +func InstallCertManager() error { + url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion) + cmd := exec.Command("kubectl", "apply", "-f", url) + if _, err := Run(cmd); err != nil { + return err + } + // Wait for cert-manager-webhook to be ready, which can take time if cert-manager + // was re-installed after uninstalling on a cluster. + cmd = exec.Command("kubectl", "wait", "deployment.apps/cert-manager-webhook", + "--for", "condition=Available", + "--namespace", "cert-manager", + "--timeout", "5m", + ) + + _, err := Run(cmd) + return err +} + +// IsCertManagerCRDsInstalled checks if any Cert Manager CRDs are installed +// by verifying the existence of key CRDs related to Cert Manager. +func IsCertManagerCRDsInstalled() bool { + // List of common Cert Manager CRDs + certManagerCRDs := []string{ + "certificates.cert-manager.io", + "issuers.cert-manager.io", + "clusterissuers.cert-manager.io", + "certificaterequests.cert-manager.io", + "orders.acme.cert-manager.io", + "challenges.acme.cert-manager.io", + } + + // Execute the kubectl command to get all CRDs + cmd := exec.Command("kubectl", "get", "crds") + output, err := Run(cmd) + if err != nil { + return false + } + + // Check if any of the Cert Manager CRDs are present + crdList := GetNonEmptyLines(output) + for _, crd := range certManagerCRDs { + for _, line := range crdList { + if strings.Contains(line, crd) { + return true + } + } } - return output, nil + return false +} + +// LoadImageToKindClusterWithName loads a local docker image to the kind cluster +func LoadImageToKindClusterWithName(name string) error { + cluster := "kind" + if v, ok := os.LookupEnv("KIND_CLUSTER"); ok { + cluster = v + } + kindOptions := []string{"load", "docker-image", name, "--name", cluster} + cmd := exec.Command("kind", kindOptions...) + _, err := Run(cmd) + return err } // GetNonEmptyLines converts given command output string into individual objects @@ -94,37 +195,60 @@ func GetNonEmptyLines(output string) []string { func GetProjectDir() (string, error) { wd, err := os.Getwd() if err != nil { - return wd, err + return wd, fmt.Errorf("failed to get current working directory: %w", err) } - wd = strings.Replace(wd, "/test/e2e", "", -1) + wd = strings.ReplaceAll(wd, "/test/e2e", "") return wd, nil } -// StringToLines read lines from a string -func StringToLines(s string) (lines []string, err error) { - scanner := bufio.NewScanner(strings.NewReader(s)) - for scanner.Scan() { - lines = append(lines, scanner.Text()) +// UncommentCode searches for target in the file and remove the comment prefix +// of the target content. The target content may span multiple lines. +func UncommentCode(filename, target, prefix string) error { + // false positive + // nolint:gosec + content, err := os.ReadFile(filename) + if err != nil { + return fmt.Errorf("failed to read file %q: %w", filename, err) } - err = scanner.Err() - return -} + strContent := string(content) -// GetOperatorImageName retrieves the operator image name to use -func GetOperatorImageName() (string, error) { - if v, ok := os.LookupEnv("OPERATOR_IMAGE_NAME"); ok { - return v, nil - } else { - return "", fmt.Errorf("Cannot find `OPERATOR_IMAGE_NAME` env variable needed for the tests") + idx := strings.Index(strContent, target) + if idx < 0 { + return fmt.Errorf("unable to find the code %q to be uncomment", target) } -} -// IsDebugEnabled ... -func IsDebugEnabled() bool { - if v, ok := os.LookupEnv("DEBUG"); ok { - if debug, err := strconv.ParseBool(v); err == nil { - return debug + out := new(bytes.Buffer) + _, err = out.Write(content[:idx]) + if err != nil { + return fmt.Errorf("failed to write to output: %w", err) + } + + scanner := bufio.NewScanner(bytes.NewBufferString(target)) + if !scanner.Scan() { + return nil + } + for { + if _, err = out.WriteString(strings.TrimPrefix(scanner.Text(), prefix)); err != nil { + return fmt.Errorf("failed to write to output: %w", err) + } + // Avoid writing a newline in case the previous line was the last in target. + if !scanner.Scan() { + break + } + if _, err = out.WriteString("\n"); err != nil { + return fmt.Errorf("failed to write to output: %w", err) } } - return false + + if _, err = out.Write(content[idx+len(target):]); err != nil { + return fmt.Errorf("failed to write to output: %w", err) + } + + // false positive + // nolint:gosec + if err = os.WriteFile(filename, out.Bytes(), 0644); err != nil { + return fmt.Errorf("failed to write file %q: %w", filename, err) + } + + return nil } diff --git a/test/yaml.go b/test/yaml.go deleted file mode 100644 index 3f622b59..00000000 --- a/test/yaml.go +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 test - -import ( - "bytes" - "os" - "path" - "path/filepath" - "runtime" - "strings" - - "github.com/davecgh/go-spew/spew" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/discovery" - discfake "k8s.io/client-go/discovery/fake" - clienttesting "k8s.io/client-go/testing" - klog "k8s.io/klog/v2" - eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/api" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/utils" -) - -const ( - CommonImageRegistryAccount = "host/namespace" - CommonImageTag = CommonImageRegistryAccount + "/image:latest" - sonataFlowSampleYamlCR = "sonataflow.org_v1alpha08_sonataflow.yaml" - SonataFlowGreetingsWithDataInputSchemaCR = "sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml" - SonataFlowGreetingsWithStaticResourcesCR = "sonataflow.org_v1alpha08_sonataflow-metainf.yaml" - SonataFlowSimpleOpsYamlCR = "sonataflow.org_v1alpha08_sonataflow-simpleops.yaml" - SonataFlowVetWithEventCR = "sonataflow.org_v1alpha08_sonataflow_vet_event.yaml" - SonataFlowGreetingsDataInputSchemaConfig = "v1_configmap_greetings_datainput.yaml" - SonataFlowGreetingsStaticFilesConfig = "v1_configmap_greetings_staticfiles.yaml" - sonataFlowPlatformYamlCR = "sonataflow.org_v1alpha08_sonataflowplatform.yaml" - sonataFlowPlatformWithBrokerYamlCR = "sonataflow.org_v1alpha08_sonataflowplatform_withBroker.yaml" - sonataFlowClusterPlatformYamlCR = "sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml" - sonataFlowBuilderConfig = "sonataflow-operator-builder-config_v1_configmap.yaml" - sonataFlowBuildSucceed = "sonataflow.org_v1alpha08_sonataflowbuild.yaml" - knativeDefaultBrokerCR = "knative_default_broker.yaml" - manifestsPath = "bundle/manifests/" - DBMigrationSonataFlowPlatform = "db_migrator_sonataflow_platform.yaml" -) - -var projectDir = "" - -func GetSonataFlow(testFile, namespace string) *operatorapi.SonataFlow { - ksw := &operatorapi.SonataFlow{} - - GetKubernetesResource(testFile, ksw) - klog.V(log.D).InfoS("Successfully read KSW", "ksw", spew.Sprint(ksw)) - ksw.Namespace = namespace - ksw.Status.FlowCRC, _ = utils.Crc32Checksum(ksw.Spec.Flow) - return ksw -} - -func GetKubernetesResource(testFile string, resource client.Object) { - yamlFile, err := os.ReadFile(path.Join(getTestDataDir(), testFile)) - if err != nil { - klog.V(log.E).ErrorS(err, "yamlFile.Get") - panic(err) - } - - // Important: Here we are reading the CR deployment file from a given path and creating an &operatorapi.SonataFlow struct - err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(resource) - if err != nil { - klog.V(log.E).ErrorS(err, "Unmarshal") - panic(err) - } -} - -func getSonataFlowClusterPlatform(testFile string) *operatorapi.SonataFlowClusterPlatform { - kscp := &operatorapi.SonataFlowClusterPlatform{} - yamlFile, err := os.ReadFile(path.Join(getTestDataDir(), testFile)) - if err != nil { - klog.V(log.E).ErrorS(err, "yamlFile.Get") - panic(err) - } - // Important: Here we are reading the CR deployment file from a given path and creating a &operatorapi.SonataFlowPlatform struct - err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(kscp) - if err != nil { - klog.V(log.E).ErrorS(err, "Unmarshal") - panic(err) - } - klog.V(log.D).InfoS("Successfully read KSCP", "kscp", kscp) - kscp.Status.Manager().InitializeConditions() - return kscp -} - -func GetSonataFlowClusterPlatformInReadyPhase(path string, namespace string) *operatorapi.SonataFlowClusterPlatform { - kscp := getSonataFlowClusterPlatform(path) - kscp.Spec.PlatformRef.Namespace = namespace - kscp.Status.Manager().MarkTrue(api.SucceedConditionType) - return kscp -} - -func getSonataFlowPlatform(testFile string) *operatorapi.SonataFlowPlatform { - ksp := &operatorapi.SonataFlowPlatform{} - yamlFile, err := os.ReadFile(path.Join(getTestDataDir(), testFile)) - if err != nil { - klog.V(log.E).ErrorS(err, "yamlFile.Get") - panic(err) - } - // Important: Here we are reading the CR deployment file from a given path and creating a &operatorapi.SonataFlowPlatform struct - err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(ksp) - if err != nil { - klog.V(log.E).ErrorS(err, "Unmarshal") - panic(err) - } - klog.V(log.D).InfoS("Successfully read KSP", "ksp", ksp) - ksp.Status.Manager().InitializeConditions() - return ksp -} - -func GetSonataFlowPlatformInReadyPhase(path string, namespace string) *operatorapi.SonataFlowPlatform { - ksp := getSonataFlowPlatform(path) - ksp.Status.Manager().MarkTrue(api.SucceedConditionType) - ksp.Namespace = namespace - return ksp -} - -func GetNewEmptySonataFlowBuild(name, namespace string) *operatorapi.SonataFlowBuild { - return &operatorapi.SonataFlowBuild{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: operatorapi.SonataFlowBuildSpec{ - BuildTemplate: operatorapi.BuildTemplate{ - Resources: corev1.ResourceRequirements{}, - Arguments: []string{}, - }, - }, - Status: operatorapi.SonataFlowBuildStatus{}, - } -} - -// GetLocalSucceedSonataFlowBuild gets a local (testdata dir ref to caller) SonataFlowBuild with Succeed status equals to true. -func GetLocalSucceedSonataFlowBuild(name, namespace string) *operatorapi.SonataFlowBuild { - yamlFile, err := os.ReadFile(path.Join(getTestDataDir(), sonataFlowBuildSucceed)) - if err != nil { - klog.ErrorS(err, "Yaml file not found on local testdata dir") - panic(err) - } - build := &operatorapi.SonataFlowBuild{} - if err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 255).Decode(build); err != nil { - klog.ErrorS(err, "Failed to unmarshal SonataFlowBuild") - panic(err) - } - build.Name = name - build.Namespace = namespace - return build -} - -func GetSonataFlowBuilderConfig(namespace string) *corev1.ConfigMap { - // Try bundle manifest first (if it exists) - cm := &corev1.ConfigMap{} - yamlFile, err := os.ReadFile(path.Join(getBundleDir(), sonataFlowBuilderConfig)) - if err == nil { - // Bundle manifest exists, decode it - err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(cm) - if err != nil { - klog.V(log.E).ErrorS(err, "Unmarshal bundle manifest") - panic(err) - } - cm.Namespace = namespace - return cm - } - - // Bundle manifest doesn't exist, create ConfigMap from source config - klog.V(log.I).InfoS("Bundle manifest not found, creating ConfigMap from source config", "file", sonataFlowBuilderConfig) - - sourceConfig, err := os.ReadFile(path.Join(getConfigDir(), "manager", "controllers_cfg.yaml")) - if err != nil { - klog.V(log.E).ErrorS(err, "Failed to read source config") - panic(err) - } - - cm = &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "sonataflow-operator-builder-config", - Namespace: namespace, - }, - Data: map[string]string{ - "controllers_cfg.yaml": string(sourceConfig), - }, - } - return cm -} - -func NewSonataFlow(filePath string, namespace string, options ...func(*operatorapi.SonataFlow)) *operatorapi.SonataFlow { - sf := GetSonataFlow(filePath, namespace) - for _, f := range options { - f(sf) - } - return sf -} - -func SetDevProfile(workflow *operatorapi.SonataFlow) { - workflow.Annotations["sonataflow.org/profile"] = "dev" -} - -func SetPreviewProfile(workflow *operatorapi.SonataFlow) { - workflow.Annotations["sonataflow.org/profile"] = "preview" -} - -func SetGitopsProfile(workflow *operatorapi.SonataFlow) { - workflow.Annotations["sonataflow.org/profile"] = "gitops" -} - -func GetBaseSonataFlow(namespace string) *operatorapi.SonataFlow { - return NewSonataFlow(sonataFlowSampleYamlCR, namespace) -} - -func GetVetEventSonataFlow(namespace string) *operatorapi.SonataFlow { - return GetSonataFlow(SonataFlowVetWithEventCR, namespace) -} - -func GetBaseSonataFlowWithDevProfile(namespace string) *operatorapi.SonataFlow { - return NewSonataFlow(sonataFlowSampleYamlCR, namespace, SetDevProfile) -} - -func GetBaseSonataFlowWithProdProfile(namespace string) *operatorapi.SonataFlow { - return NewSonataFlow(sonataFlowSampleYamlCR, namespace, SetPreviewProfile) -} - -// GetBaseSonataFlowWithPreviewProfile gets a base workflow that has a pre-built image set in podTemplate. -func GetBaseSonataFlowWithPreviewProfile(namespace string) *operatorapi.SonataFlow { - return NewSonataFlow(SonataFlowSimpleOpsYamlCR, namespace) -} - -func GetBaseSonataFlowWithGitopsProfile(namespace string) *operatorapi.SonataFlow { - return NewSonataFlow(sonataFlowSampleYamlCR, namespace, SetGitopsProfile) -} - -func GetBaseClusterPlatformInReadyPhase(namespace string) *operatorapi.SonataFlowClusterPlatform { - return GetSonataFlowClusterPlatformInReadyPhase(sonataFlowClusterPlatformYamlCR, namespace) -} - -func GetBasePlatformInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { - return GetSonataFlowPlatformInReadyPhase(sonataFlowPlatformYamlCR, namespace) -} - -func GetBaseSonataFlowPlatformInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { - return GetSonataFlowPlatformInReadyPhase(DBMigrationSonataFlowPlatform, namespace) -} - -func GetBasePlatformWithBaseImageInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { - platform := GetBasePlatform() - platform.Namespace = namespace - platform.Status.Manager().MarkTrue(api.SucceedConditionType) - platform.Spec.Build.Config.BaseImage = CommonImageTag - return platform -} - -func GetBasePlatformWithDevBaseImageInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { - platform := GetBasePlatform() - platform.Namespace = namespace - platform.Status.Manager().MarkTrue(api.SucceedConditionType) - platform.Spec.DevMode.BaseImage = CommonImageTag - return platform -} - -func GetBasePlatform() *operatorapi.SonataFlowPlatform { - return getSonataFlowPlatform(sonataFlowPlatformYamlCR) -} - -func GetBasePlatformWithBroker() *operatorapi.SonataFlowPlatform { - return getSonataFlowPlatform(sonataFlowPlatformWithBrokerYamlCR) -} - -func GetBasePlatformWithBrokerInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { - return GetSonataFlowPlatformInReadyPhase(sonataFlowPlatformWithBrokerYamlCR, namespace) -} - -func GetPathFromDataDirectory(join ...string) string { - return filepath.Join(append([]string{getTestDataDir()}, join...)...) -} - -func GetPathFromE2EDirectory(join ...string) string { - return filepath.Join(append([]string{getProjectDir(), "test", "e2e", "testdata"}, join...)...) -} - -// getTestDataDir gets the testdata directory containing every sample out there from test/testdata. -// It should be used for every testing unit within the module. -func getTestDataDir() string { - return path.Join(getProjectDir(), "test", "testdata") -} - -func getBundleDir() string { - return path.Join(getProjectDir(), manifestsPath) -} - -func getConfigDir() string { - return path.Join(getProjectDir(), "config") -} - -func getProjectDir() string { - // we only have to do this once - if len(projectDir) > 0 { - return projectDir - } - // file is the current caller relative filename (this file yaml.go) from GOPATH/src - _, filename, _, _ := runtime.Caller(0) - // remove the filename and the "test" directory - filename = filepath.Dir(filepath.Dir(filename)) - wd, _ := os.Getwd() - for { - if strings.HasSuffix(wd, filename) { - break - } - wd = filepath.Dir(wd) - } - projectDir = wd - if _, err := os.Lstat(projectDir); err != nil { - panic("Failed to read project directory to run tests: " + err.Error()) - } - - return projectDir -} - -func CreateFakeKnativeAndMonitoringDiscoveryClient() discovery.DiscoveryInterface { - return &discfake.FakeDiscovery{ - Fake: &clienttesting.Fake{ - Resources: []*metav1.APIResourceList{ - {GroupVersion: "serving.knative.dev/v1"}, - {GroupVersion: "eventing.knative.dev/v1"}, - {GroupVersion: "monitoring.coreos.com/v1"}, - }, - }, - } -} - -func GetDefaultBroker(namespace string) *eventingv1.Broker { - broker := &eventingv1.Broker{} - GetKubernetesResource(knativeDefaultBrokerCR, broker) - broker.Namespace = namespace - return broker -} diff --git a/utils/client.go b/utils/client.go index 1d984c31..108ee773 100644 --- a/utils/client.go +++ b/utils/client.go @@ -37,8 +37,8 @@ func GetClient() client.Client { } // SetClient is meant for internal use only. Don't call it! -func SetClient(client client.Client) { - k8sClient = client +func SetClient(c client.Client) { + k8sClient = c } // GetDynamicClient default dynamic client created by the main operator's thread. diff --git a/utils/common.go b/utils/common.go index 51dfff7d..154b85d4 100644 --- a/utils/common.go +++ b/utils/common.go @@ -21,10 +21,6 @@ package utils import ( "os" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/api/metadata" ) const ( @@ -36,34 +32,6 @@ const ( LatestImageTag = "latest" ) -// GetOperatorIDAnnotation to safely get the operator id annotation value. -func GetOperatorIDAnnotation(obj metav1.Object) string { - if obj == nil || obj.GetAnnotations() == nil { - return "" - } - - if operatorId, ok := obj.GetAnnotations()[metadata.OperatorIDAnnotation]; ok { - return operatorId - } - - return "" -} - -func OperatorID() string { - // TODO: what's this KAMEL_ ? - return envOrDefault("", "KAMEL_OPERATOR_ID", "OPERATOR_ID") -} - -func envOrDefault(def string, envs ...string) string { - for i := range envs { - if val := os.Getenv(envs[i]); val != "" { - return val - } - } - - return def -} - // Pbool returns a pointer to a boolean func Pbool(b bool) *bool { return &b diff --git a/utils/crc_test.go b/utils/crc_test.go index 3a304fe8..3cf4e770 100644 --- a/utils/crc_test.go +++ b/utils/crc_test.go @@ -92,7 +92,7 @@ func TestCrc32Checksum_ReturnType(t *testing.T) { } // The result should be assignable to int32 - var _ int32 = result + _ = result // Verify zero value case zeroResult, _ := Crc32Checksum("") diff --git a/utils/kubernetes/autoscaling.go b/utils/kubernetes/autoscaling.go index bc0a591d..0e0297e8 100644 --- a/utils/kubernetes/autoscaling.go +++ b/utils/kubernetes/autoscaling.go @@ -39,11 +39,11 @@ func FindHPAForDeployment(ctx context.Context, c client.Client, namespace string return findHPAForTarget(ctx, c, namespace, "apps/v1", "Deployment", name) } -// FindHPAForWorkflow returns the HorizontalPodAutoscaler targeting a workflow in a given namespace, or nil if it +// FindHPAForLogicFlowRuntime returns the HorizontalPodAutoscaler targeting a LogicFlowRuntime in a given namespace, or nil if it // doesn't exist. -// Note: By k8s definition, the HorizontalPodAutoscaler must belong to the same namespace as the managed workflow. -func FindHPAForWorkflow(ctx context.Context, c client.Client, namespace string, name string) (*autoscalingv2.HorizontalPodAutoscaler, error) { - return findHPAForTarget(ctx, c, namespace, "sonataflow.org/v1alpha08", "SonataFlow", name) +// Note: By k8s definition, the HorizontalPodAutoscaler must belong to the same namespace as the managed runtime. +func FindHPAForLogicFlowRuntime(ctx context.Context, c client.Client, namespace string, name string) (*autoscalingv2.HorizontalPodAutoscaler, error) { + return findHPAForTarget(ctx, c, namespace, "logic.kubesmarts.org/v1", "LogicFlowRuntime", name) } func findHPAForTarget(ctx context.Context, c client.Client, namespace string, apiVersion string, kind string, name string) (*autoscalingv2.HorizontalPodAutoscaler, error) { @@ -114,16 +114,16 @@ func IsHPAndTargetsADeployment(obj client.Object) (*autoscalingv2.HorizontalPodA return IsHPAndTargetsAKind(obj, "Deployment") } -// IsHPAndTargetsASonataFlow returns (*autoscalingv2.HorizontalPodAutoscaler, true) if the object is a HorizontalPodAutoscaler -// and targets a SonataFlow, (nil, false) in other cases. -func IsHPAndTargetsASonataFlow(obj client.Object) (*autoscalingv2.HorizontalPodAutoscaler, bool) { - return IsHPAndTargetsAKind(obj, "SonataFlow") +// IsHPAndTargetsALogicFlowRuntime returns (*autoscalingv2.HorizontalPodAutoscaler, true) if the object is a HorizontalPodAutoscaler +// and targets a LogicFlowRuntime, (nil, false) in other cases. +func IsHPAndTargetsALogicFlowRuntime(obj client.Object) (*autoscalingv2.HorizontalPodAutoscaler, bool) { + return IsHPAndTargetsAKind(obj, "LogicFlowRuntime") } -// IsHPAndTargetsASonataFlowAsBool returns true if the object is a HorizontalPodAutoscaler and targets a SonataFlow, +// IsHPAndTargetsALogicFlowRuntimeAsBool returns true if the object is a HorizontalPodAutoscaler and targets a LogicFlowRuntime, // false in other cases. -func IsHPAndTargetsASonataFlowAsBool(obj client.Object) bool { - _, ok := IsHPAndTargetsAKind(obj, "SonataFlow") +func IsHPAndTargetsALogicFlowRuntimeAsBool(obj client.Object) bool { + _, ok := IsHPAndTargetsAKind(obj, "LogicFlowRuntime") return ok } diff --git a/utils/kubernetes/collection.go b/utils/kubernetes/collection.go deleted file mode 100644 index 5d0f2ab6..00000000 --- a/utils/kubernetes/collection.go +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - - "github.com/kubesmarts/logic-operator/api/metadata" - - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - - routev1 "github.com/openshift/api/route/v1" -) - -// A Collection is a container of Kubernetes resources. -type Collection struct { - items []ctrl.Object -} - -// NewCollection creates a new empty collection. -func NewCollection(objects ...ctrl.Object) *Collection { - collection := Collection{ - items: make([]ctrl.Object, 0, len(objects)), - } - - collection.items = append(collection.items, objects...) - - return &collection -} - -// Size returns the number of resources belonging to the collection. -func (c *Collection) Size() int { - return len(c.items) -} - -// Items returns all resources belonging to the collection. -func (c *Collection) Items() []ctrl.Object { - return c.items -} - -// AsKubernetesList returns all resources wrapped in a Kubernetes list. -func (c *Collection) AsKubernetesList() *corev1.List { - lst := corev1.List{ - TypeMeta: metav1.TypeMeta{ - Kind: "List", - APIVersion: "v1", - }, - Items: make([]runtime.RawExtension, 0, len(c.items)), - } - for _, res := range c.items { - raw := runtime.RawExtension{ - Object: res, - } - lst.Items = append(lst.Items, raw) - } - return &lst -} - -// Add adds a resource to the collection. -func (c *Collection) Add(resource ctrl.Object) { - if resource != nil { - c.items = append(c.items, resource) - } -} - -// AddFirst adds a resource to the head of the collection. -func (c *Collection) AddFirst(resource ctrl.Object) { - if resource != nil { - c.items = append([]ctrl.Object{resource}, c.items...) - } -} - -// AddAll adds all resources to the collection. -func (c *Collection) AddAll(resource []ctrl.Object) { - c.items = append(c.items, resource...) -} - -// VisitDeployment executes the visitor function on all Deployment resources. -func (c *Collection) VisitDeployment(visitor func(*appsv1.Deployment)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*appsv1.Deployment); ok { - visitor(conv) - } - }) -} - -// VisitDeploymentE executes the visitor function on all Deployment resources. -func (c *Collection) VisitDeploymentE(visitor func(*appsv1.Deployment) error) error { - return c.VisitE(func(res runtime.Object) error { - if conv, ok := res.(*appsv1.Deployment); ok { - return visitor(conv) - } - - return nil - }) -} - -// GetDeployment returns a Deployment that matches the given function. -func (c *Collection) GetDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment { - var retValue *appsv1.Deployment - c.VisitDeployment(func(re *appsv1.Deployment) { - if filter(re) { - retValue = re - } - }) - return retValue -} - -// GetDeploymentForWorkflow returns a Deployment for the given workflow. -func (c *Collection) GetDeploymentForWorkflow(workflow *operatorapi.SonataFlow) *appsv1.Deployment { - if workflow == nil { - return nil - } - - return c.GetDeployment(func(d *appsv1.Deployment) bool { - return d.ObjectMeta.Labels[metadata.Name] == workflow.Name - }) -} - -// HasDeployment returns true if a deployment matching the given condition is present. -func (c *Collection) HasDeployment(filter func(*appsv1.Deployment) bool) bool { - return c.GetDeployment(filter) != nil -} - -// RemoveDeployment removes and returns a Deployment that matches the given function. -func (c *Collection) RemoveDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment { - res := c.Remove(func(res runtime.Object) bool { - if conv, ok := res.(*appsv1.Deployment); ok { - return filter(conv) - } - return false - }) - if res == nil { - return nil - } - deploy, ok := res.(*appsv1.Deployment) - if !ok { - return nil - } - - return deploy -} - -// VisitConfigMap executes the visitor function on all ConfigMap resources. -func (c *Collection) VisitConfigMap(visitor func(*corev1.ConfigMap)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*corev1.ConfigMap); ok { - visitor(conv) - } - }) -} - -// GetConfigMap returns a ConfigMap that matches the given function. -func (c *Collection) GetConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap { - var retValue *corev1.ConfigMap - c.VisitConfigMap(func(re *corev1.ConfigMap) { - if filter(re) { - retValue = re - } - }) - return retValue -} - -// RemoveConfigMap removes and returns a ConfigMap that matches the given function. -func (c *Collection) RemoveConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap { - res := c.Remove(func(res runtime.Object) bool { - if conv, ok := res.(*corev1.ConfigMap); ok { - return filter(conv) - } - return false - }) - if res == nil { - return nil - } - cm, ok := res.(*corev1.ConfigMap) - if !ok { - return nil - } - - return cm -} - -// VisitService executes the visitor function on all Service resources. -func (c *Collection) VisitService(visitor func(*corev1.Service)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*corev1.Service); ok { - visitor(conv) - } - }) -} - -// GetService returns a Service that matches the given function. -func (c *Collection) GetService(filter func(*corev1.Service) bool) *corev1.Service { - var retValue *corev1.Service - c.VisitService(func(re *corev1.Service) { - if filter(re) { - retValue = re - } - }) - return retValue -} - -// GetServiceForWorkflow returns a user Service for the given workflow. -func (c *Collection) GetServiceForWorkflow(workflow *operatorapi.SonataFlow) *corev1.Service { - if workflow == nil { - return nil - } - return c.GetService(func(s *corev1.Service) bool { - return s.ObjectMeta.Labels != nil && s.ObjectMeta.Labels[metadata.Label] == workflow.Name - }) -} - -// VisitRoute executes the visitor function on all Route resources. -func (c *Collection) VisitRoute(visitor func(*routev1.Route)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*routev1.Route); ok { - visitor(conv) - } - }) -} - -// GetRoute returns a Route that matches the given function. -func (c *Collection) GetRoute(filter func(*routev1.Route) bool) *routev1.Route { - var retValue *routev1.Route - c.VisitRoute(func(re *routev1.Route) { - if filter(re) { - retValue = re - } - }) - return retValue -} - -// GetCronJob returns a CronJob that matches the given function. -func (c *Collection) GetCronJob(filter func(job *batchv1.CronJob) bool) *batchv1.CronJob { - var retValue *batchv1.CronJob - c.VisitCronJob(func(re *batchv1.CronJob) { - if filter(re) { - retValue = re - } - }) - return retValue -} - -// VisitCronJob executes the visitor function on all CronJob resources. -func (c *Collection) VisitCronJob(visitor func(*batchv1.CronJob)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*batchv1.CronJob); ok { - visitor(conv) - } - }) -} - -// VisitCronJobE executes the visitor function on all CronJob resources. -func (c *Collection) VisitCronJobE(visitor func(*batchv1.CronJob) error) error { - return c.VisitE(func(res runtime.Object) error { - if conv, ok := res.(*batchv1.CronJob); ok { - return visitor(conv) - } - - return nil - }) -} - -// GetContainer --. -func (c *Collection) GetContainer(filter func(container *corev1.Container) bool) *corev1.Container { - var retValue *corev1.Container - - c.VisitContainer(func(container *corev1.Container) { - if filter(container) { - retValue = container - } - }) - - return retValue -} - -// GetContainerByName --. -func (c *Collection) GetContainerByName(name string) *corev1.Container { - return c.GetContainer(func(c *corev1.Container) bool { - return c.Name == name - }) -} - -// VisitContainer executes the visitor function on all Containers inside deployments or other resources. -func (c *Collection) VisitContainer(visitor func(container *corev1.Container)) { - c.VisitDeployment(func(d *appsv1.Deployment) { - for idx := range d.Spec.Template.Spec.Containers { - cntref := &d.Spec.Template.Spec.Containers[idx] - visitor(cntref) - } - }) -} - -// GetController returns the controller associated with the workflow (e.g. Deployment). -func (c *Collection) GetController(filter func(object ctrl.Object) bool) ctrl.Object { - d := c.GetDeployment(func(deployment *appsv1.Deployment) bool { - return filter(deployment) - }) - if d != nil { - return d - } - return nil -} - -// VisitPodSpec executes the visitor function on all PodSpec inside deployments or other resources. -func (c *Collection) VisitPodSpec(visitor func(container *corev1.PodSpec)) { - c.VisitDeployment(func(d *appsv1.Deployment) { - visitor(&d.Spec.Template.Spec) - }) -} - -// VisitPodTemplateMeta executes the visitor function on all PodTemplate metadata inside deployments or other resources. -func (c *Collection) VisitPodTemplateMeta(visitor func(meta *metav1.ObjectMeta)) { - c.VisitDeployment(func(d *appsv1.Deployment) { - visitor(&d.Spec.Template.ObjectMeta) - }) -} - -// VisitMetaObject executes the visitor function on all meta.Object resources. -func (c *Collection) VisitMetaObject(visitor func(metav1.Object)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(metav1.Object); ok { - visitor(conv) - } - }) -} - -// Visit executes the visitor function on all resources. -func (c *Collection) Visit(visitor func(runtime.Object)) { - for _, res := range c.items { - visitor(res) - } -} - -// VisitE executes the visitor function on all resources breaking if the visitor function -// returns an error. -func (c *Collection) VisitE(visitor func(runtime.Object) error) error { - for _, res := range c.items { - if err := visitor(res); err != nil { - return err - } - } - - return nil -} - -// Remove removes the given element from the collection and returns it. -func (c *Collection) Remove(selector func(runtime.Object) bool) runtime.Object { - for idx, res := range c.items { - if selector(res) { - c.items = append(c.items[0:idx], c.items[idx+1:]...) - return res - } - } - return nil -} - -func (c *Collection) VisitPodMonitor(visitor func(*monitoringv1.PodMonitor)) { - c.Visit(func(res runtime.Object) { - if conv, ok := res.(*monitoringv1.PodMonitor); ok { - visitor(conv) - } - }) -} - -func (c *Collection) GetPodMonitor(filter func(*monitoringv1.PodMonitor) bool) *monitoringv1.PodMonitor { - var retValue *monitoringv1.PodMonitor - c.VisitPodMonitor(func(podMonitor *monitoringv1.PodMonitor) { - if filter(podMonitor) { - retValue = podMonitor - } - }) - return retValue -} diff --git a/utils/kubernetes/deployment.go b/utils/kubernetes/deployment.go deleted file mode 100644 index 58665226..00000000 --- a/utils/kubernetes/deployment.go +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "errors" - "fmt" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1 "k8s.io/api/apps/v1" - v1 "k8s.io/api/core/v1" - "k8s.io/klog/v2" - - k8serrors "k8s.io/apimachinery/pkg/api/errors" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/log" - "github.com/kubesmarts/logic-operator/workflowproj" -) - -const ( - // this const is available here https://github.com/kubernetes/kubernetes/blob/6e0cb243d57592c917fe449dde20b0e246bc66be/pkg/controller/deployment/util/deployment_util.go#L100 - // but it doesn't worth the dependency. - deploymentMinimumReplicasUnavailable = "MinimumReplicasUnavailable" -) - -// IsDeploymentAvailable verifies if the Deployment conditions match the Available status -func IsDeploymentAvailable(deployment *appsv1.Deployment) bool { - return isDeploymentInCondition(deployment, appsv1.DeploymentAvailable, v1.ConditionTrue) -} - -// IsDeploymentFailed returns true in case of Deployment not available (IsDeploymentAvailable returns false) or it has a condition of -// DeploymentReplicaFailure == true. -func IsDeploymentFailed(deployment *appsv1.Deployment) bool { - if IsDeploymentAvailable(deployment) { - return false - } - return isDeploymentInCondition(deployment, appsv1.DeploymentReplicaFailure, v1.ConditionTrue) -} - -func isDeploymentInCondition(deployment *appsv1.Deployment, conditionType appsv1.DeploymentConditionType, status v1.ConditionStatus) bool { - for _, condition := range deployment.Status.Conditions { - if condition.Type == conditionType && - condition.Status == status { - return true - } - } - return false -} - -// IsDeploymentMinimumReplicasUnavailable verifies if the deployment has the minimum replicas available -func IsDeploymentMinimumReplicasUnavailable(deployment *appsv1.Deployment) bool { - for _, condition := range deployment.Status.Conditions { - if condition.Type == appsv1.DeploymentAvailable && - condition.Status == v1.ConditionFalse && - condition.Reason == deploymentMinimumReplicasUnavailable { - return true - } - } - return false -} - -// GetDeploymentUnavailabilityMessage returns a string explaining why the given deployment is unavailable. If empty, there's no replica failure. -// Note that the Deployment might be available, but a second replica failed to scale. Always check IsDeploymentAvailable. -// -// See: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#failed-deployment -func GetDeploymentUnavailabilityMessage(deployment *appsv1.Deployment) string { - for _, condition := range deployment.Status.Conditions { - if condition.Type == appsv1.DeploymentProgressing && - condition.Status == v1.ConditionFalse { - return fmt.Sprintf("deployment %s unavailable: reason %s, message %s", deployment.Name, condition.Reason, condition.Message) - } - if condition.Type == appsv1.DeploymentReplicaFailure && - condition.Status == v1.ConditionTrue { - return fmt.Sprintf("deployment %s unavailable: reason %s, message %s", deployment.Name, condition.Reason, condition.Message) - } - } - return "" -} - -// MarkDeploymentToRollout marks the given Deployment to restart now. The object must be updated. -// Code adapted from here: https://github.com/kubernetes/kubectl/blob/release-1.26/pkg/polymorphichelpers/objectrestarter.go#L44 -func MarkDeploymentToRollout(deployment *appsv1.Deployment) error { - if deployment.Spec.Paused { - return errors.New("can't restart paused deployment (run rollout resume first)") - } - if deployment.Spec.Template.ObjectMeta.Annotations == nil { - deployment.Spec.Template.ObjectMeta.Annotations = make(map[string]string) - } - - klog.V(log.I).Infof("Triggering restart of %s", deployment.Name) - deployment.Spec.Template.ObjectMeta.Annotations[metadata.RestartedAt] = time.Now().Format(time.RFC3339) - return nil -} - -// AnnotateDeploymentConfigChecksum adds the checksum/config annotation to the template annotations of the Deployment to set the current configuration. -// If the checksum has changed from the previous value, the restartedAt annotation is also added and a new rollout is started. -// Code adapted from here: https://github.com/kubernetes/kubectl/blob/release-1.26/pkg/polymorphichelpers/objectrestarter.go#L44 -func AnnotateDeploymentConfigChecksum(workflow *operatorapi.SonataFlow, deployment *appsv1.Deployment, userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) error { - if deployment.Spec.Paused { - return errors.New("can't restart paused deployment (run rollout resume first)") - } - if deployment.Spec.Template.ObjectMeta.Annotations == nil { - deployment.Spec.Template.ObjectMeta.Annotations = make(map[string]string) - } - - currentChecksum, ok := deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] - if !ok { - currentChecksum = "" - } - newChecksum, err := calculateHash(userPropsCM, managedPropsCM, workflow) - if err != nil { - return err - } - if newChecksum != currentChecksum { - klog.V(log.I).Infof("Updating checksum of %s", deployment.Name) - deployment.Spec.Template.ObjectMeta.Annotations[metadata.Checksum] = newChecksum - if currentChecksum != "" { - klog.V(log.I).Infof("Triggering rollout of %s", deployment.Name) - deployment.Spec.Template.ObjectMeta.Annotations[metadata.RestartedAt] = time.Now().Format(time.RFC3339) - } - } else { - klog.V(log.I).Infof("Skipping update of deployment %s, checksum unchanged", deployment.Name) - } - return nil -} - -func dataFromCM(cm *v1.ConfigMap, key string) string { - data, hasKey := cm.Data[key] - if !hasKey { - return "" - } - return data -} - -func calculateHash(userPropsCM, managedPropsCM *v1.ConfigMap, workflow *operatorapi.SonataFlow) (string, error) { - aggregatedProps := fmt.Sprintf("%s,%s", dataFromCM(userPropsCM, workflowproj.ApplicationPropertiesFileName), - dataFromCM(managedPropsCM, workflowproj.GetManagedPropertiesFileName(workflow))) - hash := sha256.New() - _, err := hash.Write([]byte(aggregatedProps)) - if err != nil { - return "", err - } - - hashInBytes := hash.Sum(nil) - hashString := hex.EncodeToString(hashInBytes) - return hashString, nil -} - -// GetContainerByName returns a pointer to the Container within the given Deployment. -// If none found, returns nil. -// It also returns the position where the container was found, -1 if none -func GetContainerByName(name string, podSpec *v1.PodSpec) (*v1.Container, int) { - if podSpec == nil { - return nil, -1 - } - for i, container := range podSpec.Containers { - if container.Name == name { - return &container, i - } - } - return nil, -1 -} - -// GetContainerPortByName returns a pointer to the ContainerPort within the given Container. -// If none found, returns nil. -// It also returns the position where the container port was found, -1 if none. -func GetContainerPortByName(name string, container *v1.Container) (*v1.ContainerPort, int) { - if container == nil { - return nil, -1 - } - for i, containerPort := range container.Ports { - if name == containerPort.Name { - return &containerPort, i - } - } - return nil, -1 -} - -// AddOrReplaceContainer replace the existing container or add if it doesn't exist in the .spec.containers attribute -func AddOrReplaceContainer(containerName string, container v1.Container, podSpec *v1.PodSpec) { - _, idx := GetContainerByName(containerName, podSpec) - if idx < 0 { - podSpec.Containers = append(podSpec.Containers, container) - } else { - podSpec.Containers[idx] = container - } -} - -// DeploymentReplicasIsGreaterThan returns true if the Deployment configured replicas is != nil, and greater than -// the given value. False in any other case. -func DeploymentReplicasIsGreaterThan(deployment *appsv1.Deployment, value int32) bool { - return deployment.Spec.Replicas != nil && *deployment.Spec.Replicas > value -} - -// DeploymentIsScaledToZero returns true if the Deployment has been explicitly scaled to zero, i.e., by setting -// the replicas == 0. False in any other case, including when replicas == nil. -func DeploymentIsScaledToZero(deployment *appsv1.Deployment) bool { - return deployment.Spec.Replicas != nil && *deployment.Spec.Replicas == int32(0) -} - -// SafeDeleteDeployment deletes a potentially existing Deployment, ignoring the not existing error. -func SafeDeleteDeployment(ctx context.Context, c client.Client, namespace, name string) error { - err := c.Delete(ctx, &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - }) - if err != nil { - if k8serrors.IsNotFound(err) { - klog.V(log.D).Infof("Deployment %s/%s was already deleted or never existed.", namespace, name) - return nil - } else { - return err - } - } - return nil -} diff --git a/utils/kubernetes/deployment_failure.go b/utils/kubernetes/deployment_failure.go index d4a58327..69baeec9 100644 --- a/utils/kubernetes/deployment_failure.go +++ b/utils/kubernetes/deployment_failure.go @@ -42,9 +42,9 @@ type DeploymentUnavailabilityReader interface { } // DeploymentTroubleshooter creates a new DeploymentUnavailabilityReader for finding out why a deployment failed -func DeploymentTroubleshooter(client client.Client, deployment *v1.Deployment, container string) DeploymentUnavailabilityReader { +func DeploymentTroubleshooter(c client.Client, deployment *v1.Deployment, container string) DeploymentUnavailabilityReader { return &deploymentUnavailabilityReader{ - c: client, + c: c, deployment: deployment, container: container, } diff --git a/utils/kubernetes/disruption_budget.go b/utils/kubernetes/disruption_budget.go deleted file mode 100644 index cfa3970a..00000000 --- a/utils/kubernetes/disruption_budget.go +++ /dev/null @@ -1,69 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" - - policyv1 "k8s.io/api/policy/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/log" -) - -// IsEmptyPodDisruptionBudgetSpec returns true if the PodDisruptionBudgetSpec is nil or has no configured values at all, -// false in any other case. -func IsEmptyPodDisruptionBudgetSpec(spec *operatorapi.PodDisruptionBudgetSpec) bool { - return spec == nil || (spec.MinAvailable == nil && spec.MaxUnavailable == nil) -} - -// ApplyPodDisruptionBudgetSpec applies an operatorapi.PodDisruptionBudgetSpec to the PodDisruptionBudget. -func ApplyPodDisruptionBudgetSpec(pdb *policyv1.PodDisruptionBudget, spec *operatorapi.PodDisruptionBudgetSpec) { - if spec.MinAvailable != nil { - pdb.Spec.MinAvailable = spec.MinAvailable - pdb.Spec.MaxUnavailable = nil - } else { - pdb.Spec.MaxUnavailable = spec.MaxUnavailable - pdb.Spec.MinAvailable = nil - } -} - -// SafeDeletePodDisruptionBudget deletes a potentially existing PodDisruptionBudget, ignoring the not existing error. -func SafeDeletePodDisruptionBudget(ctx context.Context, c client.Client, namespace, name string) error { - err := c.Delete(ctx, &policyv1.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - }) - if err != nil { - if errors.IsNotFound(err) { - klog.V(log.D).Infof("PodDisruptionBudget %s/%s was already deleted or never existed.", namespace, name) - return nil - } else { - return err - } - } - return nil -} diff --git a/utils/kubernetes/replace.go b/utils/kubernetes/replace.go deleted file mode 100644 index 65c0deda..00000000 --- a/utils/kubernetes/replace.go +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 kubernetes - -import ( - "context" - "fmt" - - client "github.com/kubesmarts/logic-operator/container-builder/client" - - "github.com/pkg/errors" - - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - routev1 "github.com/openshift/api/route/v1" -) - -// ReplaceResource allows to completely replace a resource on Kubernetes, taking care of immutable fields and resource versions. -func ReplaceResource(ctx context.Context, c client.Client, res ctrl.Object) (bool, error) { - replaced := false - err := c.Create(ctx, res) - if err != nil && k8serrors.IsAlreadyExists(err) { - replaced = true - existing, ok := res.DeepCopyObject().(ctrl.Object) - if !ok { - return replaced, fmt.Errorf("type assertion failed: %v", res.DeepCopyObject()) - } - err = c.Get(ctx, ctrl.ObjectKeyFromObject(existing), existing) - if err != nil { - return replaced, err - } - mapRequiredMeta(existing, res) - mapRequiredServiceData(existing, res) - mapRequiredRouteData(existing, res) - err = c.Update(ctx, res) - } - if err != nil { - return replaced, errors.Wrap(err, "could not create or replace "+findResourceDetails(res)) - } - return replaced, nil -} - -func mapRequiredMeta(from ctrl.Object, to ctrl.Object) { - to.SetResourceVersion(from.GetResourceVersion()) -} - -func mapRequiredServiceData(from runtime.Object, to runtime.Object) { - if fromC, ok := from.(*corev1.Service); ok { - if toC, ok := to.(*corev1.Service); ok { - toC.Spec.ClusterIP = fromC.Spec.ClusterIP - } - } -} - -func mapRequiredRouteData(from runtime.Object, to runtime.Object) { - if fromC, ok := from.(*routev1.Route); ok { - if toC, ok := to.(*routev1.Route); ok { - toC.Spec.Host = fromC.Spec.Host - } - } -} - -func findResourceDetails(res ctrl.Object) string { - if res == nil { - return "nil resource" - } - return res.GetObjectKind().GroupVersionKind().String() + " " + res.GetName() -} diff --git a/utils/kubernetes/service.go b/utils/kubernetes/service.go index 53deb202..375e2d4a 100644 --- a/utils/kubernetes/service.go +++ b/utils/kubernetes/service.go @@ -41,11 +41,11 @@ func retrieveServiceHost(service *v1.Service) string { // RetrieveServiceURL function that based on the service name, namespace and eventually the nodeport, will provide the service URI func RetrieveServiceURL(service *v1.Service) (*apis.URL, error) { - url := url.URL{ + u := url.URL{ Scheme: "http", Host: retrieveServiceHost(service), Path: service.Name} - return apis.ParseURL(url.String()) + return apis.ParseURL(u.String()) } // GetServicePortByName returns a pointer to the ServicePort within the given Service. diff --git a/utils/kubernetes/service_test.go b/utils/kubernetes/service_test.go index 793a3433..43bb4f14 100644 --- a/utils/kubernetes/service_test.go +++ b/utils/kubernetes/service_test.go @@ -26,10 +26,12 @@ import ( v1 "k8s.io/api/core/v1" ) +const testWorkflowName = "workflow" + func Test_retrievingKubernetesServiceHost(t *testing.T) { t.Run("verify that the service host is returned with the default cluster name on default namespace", func(t *testing.T) { svc := &v1.Service{} - svc.Name = "workflow" + svc.Name = testWorkflowName host := retrieveServiceHost(svc) assert.NotNil(t, host) @@ -39,7 +41,7 @@ func Test_retrievingKubernetesServiceHost(t *testing.T) { t.Run("verify that the service host is returned with the default cluster name on non-default namespace", func(t *testing.T) { svc := &v1.Service{} - svc.Name = "workflow" + svc.Name = testWorkflowName svc.Namespace = "ns" host := retrieveServiceHost(svc) @@ -52,8 +54,8 @@ func Test_retrievingKubernetesServiceHost(t *testing.T) { func Test_retrievingKubernetesServiceURL(t *testing.T) { t.Run("verify that the service URL is returned with the default cluster name on default namespace", func(t *testing.T) { svc := &v1.Service{} - svc.Name = "workflow" - RetrieveServiceURL(svc) + svc.Name = testWorkflowName + _, _ = RetrieveServiceURL(svc) //nolint:errcheck url, err := RetrieveServiceURL(svc) @@ -65,9 +67,9 @@ func Test_retrievingKubernetesServiceURL(t *testing.T) { t.Run("verify that the service URL is returned with the default cluster name on non-default namespace", func(t *testing.T) { svc := &v1.Service{} - svc.Name = "workflow" + svc.Name = testWorkflowName svc.Namespace = "ns" - RetrieveServiceURL(svc) + _, _ = RetrieveServiceURL(svc) //nolint:errcheck url, err := RetrieveServiceURL(svc) diff --git a/utils/kubernetes/volumes.go b/utils/kubernetes/volumes.go index e43553a0..5871c403 100644 --- a/utils/kubernetes/volumes.go +++ b/utils/kubernetes/volumes.go @@ -121,9 +121,7 @@ func AddOrReplaceVolume(podSpec *corev1.PodSpec, volumes ...corev1.Volume) { volumesToAdd = append(volumesToAdd, volume) } } - for _, volume := range volumesToAdd { - podSpec.Volumes = append(podSpec.Volumes, volume) - } + podSpec.Volumes = append(podSpec.Volumes, volumesToAdd...) } // AddOrReplaceVolumeMount same as AddOrReplaceVolume, but with VolumeMounts in a specific container diff --git a/utils/openshift/route.go b/utils/openshift/route.go deleted file mode 100644 index 6d01ba04..00000000 --- a/utils/openshift/route.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 openshift - -import ( - v1 "github.com/openshift/api/route/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kubesmarts/logic-operator/workflowproj" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func RouteForWorkflow(workflow *operatorapi.SonataFlow) (*v1.Route, error) { - route := &v1.Route{ - ObjectMeta: metav1.ObjectMeta{ - Name: workflow.Name, - Namespace: workflow.Namespace, - Labels: workflowproj.GetMergedLabels(workflow), - }, - Spec: v1.RouteSpec{ - To: v1.RouteTargetReference{ - Kind: "Service", - Name: workflow.Name, - }, - TLS: &v1.TLSConfig{ - Termination: v1.TLSTerminationEdge, - }, - }, - } - return route, nil -} diff --git a/utils/openshift/route_test.go b/utils/openshift/route_test.go deleted file mode 100644 index 298aacb4..00000000 --- a/utils/openshift/route_test.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 openshift - -import ( - "testing" - - v1 "github.com/openshift/api/route/v1" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const ( - WorkflowName = "helloworld" - WorkflowNamespace = "usecase1" -) - -func TestRouteForWorkflow(t *testing.T) { - workflow := &operatorapi.SonataFlow{ - ObjectMeta: metav1.ObjectMeta{ - Name: WorkflowName, - Namespace: WorkflowNamespace, - }, - } - route, err := RouteForWorkflow(workflow) - assert.NotNil(t, route) - assert.Nil(t, err) - assert.Equal(t, WorkflowName, route.ObjectMeta.Name) - assert.Equal(t, WorkflowNamespace, route.ObjectMeta.Namespace) - assert.Equal(t, "Service", route.Spec.To.Kind) - assert.Equal(t, WorkflowName, route.Spec.To.Name) - assert.Equal(t, v1.TLSTerminationEdge, route.Spec.TLS.Termination) -} diff --git a/utils/resources/resources.go b/utils/resources/resources.go deleted file mode 100644 index 82b2fa2e..00000000 --- a/utils/resources/resources.go +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 resources - -import ( - "context" - "io/ioutil" - "net/http" - "os" - "path/filepath" - "strings" - - "github.com/pkg/errors" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kubesmarts/logic-operator/container-builder/client" - "github.com/kubesmarts/logic-operator/utils" - - v08 "github.com/kubesmarts/logic-operator/api/v1alpha08" - "github.com/kubesmarts/logic-operator/utils/kubernetes" -) - -var builderResourcesPath = utils.GetEnv("BUILDER_RESOURCES_PATH", "/usr/local/etc/serverless-operator") - -// ResourceCustomizer can be used to inject code that changes the objects before they are created. -type ResourceCustomizer func(object ctrl.Object) ctrl.Object - -// IdentityResourceCustomizer is a ResourceCustomizer that does nothing. -var IdentityResourceCustomizer = func(object ctrl.Object) ctrl.Object { - return object -} - -func ResourcesOrCollect(ctx context.Context, c client.Client, namespace string, collection *kubernetes.Collection, - force bool, customizer ResourceCustomizer, names ...string) error { - for _, name := range names { - if err := ResourceOrCollect(ctx, c, namespace, collection, force, customizer, name); err != nil { - return err - } - } - return nil -} - -func ResourceOrCollect(ctx context.Context, c client.Client, namespace string, collection *kubernetes.Collection, - force bool, customizer ResourceCustomizer, name string) error { - - content, err := ResourceAsString(name) - if err != nil { - return err - } - - obj, err := kubernetes.LoadResourceFromYaml(c.GetScheme(), content) - if err != nil { - return err - } - - return ObjectOrCollect(ctx, c, namespace, collection, force, customizer(obj)) -} - -func ObjectOrCollect(ctx context.Context, c client.Client, namespace string, collection *kubernetes.Collection, force bool, obj ctrl.Object) error { - if collection != nil { - // Adding to the collection before setting the namespace - collection.Add(obj) - return nil - } - - obj.SetNamespace(namespace) - - if obj.GetObjectKind().GroupVersionKind().Kind == "PersistentVolumeClaim" { - if err := c.Create(ctx, obj); err != nil && !k8serrors.IsAlreadyExists(err) { - return err - } - } - - if force { - if _, err := kubernetes.ReplaceResource(ctx, c, obj); err != nil { - return err - } - // For some resources, also reset the status - if obj.GetObjectKind().GroupVersionKind().Kind == v08.SonataFlowPlatformKind { - if err := c.Status().Update(ctx, obj); err != nil { - return err - } - } - return nil - } - - // Just try to create them - return c.Create(ctx, obj) -} - -// ResourceAsString returns the named resource content as string. -func ResourceAsString(name string) (string, error) { - data, err := Resource(name) - return string(data), err -} - -// Resource provides an easy way to access to embedded assets. -func Resource(name string) ([]byte, error) { - name = strings.Trim(name, " ") - if !strings.HasPrefix(name, builderResourcesPath) { - name = builderResourcesPath + name - } - - file, err := openAsset(name) - if err != nil { - return nil, errors.Wrapf(err, "cannot access resource file %s", name) - } - - data, err := ioutil.ReadAll(file) - if err != nil { - _ = file.Close() - return nil, errors.Wrapf(err, "cannot access resource file %s", name) - } - - return data, file.Close() -} - -// DirExists tells if a directory exists and can be listed for files. -func DirExists(dirName string) bool { - if _, err := openAsset(dirName); err != nil { - return false - } - return true -} - -// WithPrefix lists all file names that begins with the give path prefix -// If pathPrefix is a path of directories then be sure to end it with a '/'. -func WithPrefix(pathPrefix string) ([]string, error) { - dirPath := filepath.Dir(pathPrefix) - - paths, err := Resources(dirPath) - if err != nil { - return nil, err - } - - var res []string - for i := range paths { - path := filepath.ToSlash(paths[i]) - if result, _ := filepath.Match(pathPrefix+"*", path); result { - res = append(res, path) - } - } - - return res, nil -} - -// Resources lists all file names in the given path (starts with '/'). -func Resources(dirName string) ([]string, error) { - dir, err := openAsset(dirName) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - - return nil, errors.Wrapf(err, "error while listing resource files %s", dirName) - } - - info, err := dir.Stat() - if err != nil { - return nil, dir.Close() - } - if !info.IsDir() { - CloseQuietly(dir) - return nil, errors.Wrapf(err, "location %s is not a directory", dirName) - } - - files, err := dir.Readdir(-1) - if err != nil { - CloseQuietly(dir) - return nil, errors.Wrapf(err, "error while listing files on directory %s", dirName) - } - - var res []string - for _, f := range files { - if !f.IsDir() { - res = append(res, filepath.Join(dirName, f.Name())) - } - } - - return res, dir.Close() -} - -func openAsset(path string) (http.File, error) { - return Open(filepath.ToSlash(path)) -} diff --git a/utils/resources/resources_support.go b/utils/resources/resources_support.go deleted file mode 100644 index ec4c2768..00000000 --- a/utils/resources/resources_support.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 resources - -import ( - "io" - "os" - "path/filepath" -) - -// CloseQuietly unconditionally close an io.Closer -// It should not be used to replace the Close statement(s). -func CloseQuietly(closer io.Closer) { - _ = closer.Close() -} - -// Open a safe wrapper of os.Open. -func Open(name string) (*os.File, error) { - return os.Open(filepath.Clean(name)) -} diff --git a/workflowproj/Makefile b/workflowproj/Makefile deleted file mode 100644 index 663f108c..00000000 --- a/workflowproj/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -.PHONY: all -all: test - -##@ Development - -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... - -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... - -.PHONY: test -test: fmt vet ## Run tests. - go test ./... -coverprofile cover.out - -.PHONY: clean -clean: - rm -rf bin/ - diff --git a/workflowproj/README.md b/workflowproj/README.md deleted file mode 100644 index 1b031ef2..00000000 --- a/workflowproj/README.md +++ /dev/null @@ -1,105 +0,0 @@ - - -# Workflow Project Handler - -Handler to programmatically convert a local SonataFlow project into Kubernetes manifests to deploy with -the operator. - -## How to - -Add this module to your project's dependencies: - -```shell -go get github.com/kiegroup/kogito-serverless-workflow/workflowproj -``` - -Then you should have access to the main entry point of this package, which is the workflow project handler builder. - -The API is simple enough to describe in a few lines: - -```go -package main - -import ( - "os" - - "github.com/apache/incubator-kie-tools/packages/sonataflow-operator/workflowproj" -) - -func Main() { - // we are ignoring errors just for demo purposes, but don't do this! - workflowFile, _ := os.Open("myworkflow.sw.json") - propertiesFile, _ := os.Open("application.properties") - specFile, _ := os.Open("myopenapi.yaml") - defer workflowFile.Close() - defer propertiesFile.Close() - defer specFile.Close() - - // create the handler - handler := workflowproj.New("mynamespace"). - WithWorkflow(workflowFile). - WithAppProperties(propertiesFile). - AddResource("myopenapi.yaml", specFile) - - // You can easily generate the Kubernetes manifests to later use client-go to deploy them in the cluster... - objs, _ := handler.AsObjects() - // client.Create(...), other stuff - - // ... or you can save the files locally to use them later or to integrate in a GitOps process - _ = handler.SaveAsKubernetesManifests("/my/dir/") -} -``` - -The `SonataFlow` custom resource generated is annotated with -the [devmode profile](https://kiegroup.github.io/kogito-docs/serverlessworkflow/latest/cloud/operator/developing-workflows.html) -. -Every other resource added to the project is a `ConfigMap` handling these resources for you. - -Given that you already have the SonataFlow -Operator [installed](https://kiegroup.github.io/kogito-docs/serverlessworkflow/latest/cloud/operator/install-serverless-operator.html) -, to deploy the generated project you can simply run: - -```shell -kubectl apply -f /my/dir/* -n "mynamespace" -``` - ---- - -Apache KIE (incubating) is an effort undergoing incubation at The Apache Software -Foundation (ASF), sponsored by the name of Apache Incubator. Incubation is -required of all newly accepted projects until a further review indicates that -the infrastructure, communications, and decision making process have stabilized -in a manner consistent with other successful ASF projects. While incubation -status is not necessarily a reflection of the completeness or stability of the -code, it does indicate that the project has yet to be fully endorsed by the ASF. - -Some of the incubating project’s releases may not be fully compliant with ASF -policy. For example, releases may have incomplete or un-reviewed licensing -conditions. What follows is a list of known issues the project is currently -aware of (note that this list, by definition, is likely to be incomplete): - -- Hibernate, an LGPL project, is being used. Hibernate is in the process of - relicensing to ASL v2 -- Some files, particularly test files, and those not supporting comments, may - be missing the ASF Licensing Header - -If you are planning to incorporate this work into your product/project, please -be aware that you will need to conduct a thorough licensing review to determine -the overall implications of including this work. For the current status of this -project through the Apache Incubator visit: -https://incubator.apache.org/projects/kie.html diff --git a/workflowproj/camelschema.go b/workflowproj/camelschema.go deleted file mode 100644 index 6406d187..00000000 --- a/workflowproj/camelschema.go +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -// camelSchema version 3.20.5. We can update this schema as we go, or add support to more than one in the future. -// See https://github.com/apache/camel/blob/camel-3.20.5/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json -const camelSchema = "{ \"$schema\" : \"http://json-schema.org/draft-04/schema#\", \"type\" : \"array\", \"items\" : { \"maxProperties\" : 1, \"definitions\" : { \"org.apache.camel.model.ProcessorDefinition\" : { \"type\" : \"object\", \"maxProperties\" : 1, \"properties\" : { \"aggregate\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.AggregateDefinition\" }, \"bean\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.BeanDefinition\" }, \"do-catch\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.CatchDefinition\" }, \"doCatch\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.CatchDefinition\" }, \"choice\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ChoiceDefinition\" }, \"circuit-breaker\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.CircuitBreakerDefinition\" }, \"circuitBreaker\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.CircuitBreakerDefinition\" }, \"claim-check\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ClaimCheckDefinition\" }, \"claimCheck\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ClaimCheckDefinition\" }, \"convert-body-to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ConvertBodyDefinition\" }, \"convertBodyTo\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ConvertBodyDefinition\" }, \"delay\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.DelayDefinition\" }, \"dynamic-router\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.DynamicRouterDefinition\" }, \"dynamicRouter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.DynamicRouterDefinition\" }, \"enrich\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.EnrichDefinition\" }, \"filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FilterDefinition\" }, \"do-finally\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FinallyDefinition\" }, \"doFinally\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FinallyDefinition\" }, \"idempotent-consumer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.IdempotentConsumerDefinition\" }, \"idempotentConsumer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.IdempotentConsumerDefinition\" }, \"in-only\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InOnlyDefinition\" }, \"inOnly\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InOnlyDefinition\" }, \"in-out\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InOutDefinition\" }, \"inOut\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InOutDefinition\" }, \"intercept\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptDefinition\" }, \"intercept-from\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptFromDefinition\" }, \"interceptFrom\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptFromDefinition\" }, \"intercept-send-to-endpoint\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptSendToEndpointDefinition\" }, \"interceptSendToEndpoint\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptSendToEndpointDefinition\" }, \"kamelet\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.KameletDefinition\" }, \"load-balance\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.LoadBalanceDefinition\" }, \"loadBalance\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.LoadBalanceDefinition\" }, \"log\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.LogDefinition\" }, \"loop\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.LoopDefinition\" }, \"marshal\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.MarshalDefinition\" }, \"multicast\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.MulticastDefinition\" }, \"on-completion\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnCompletionDefinition\" }, \"onCompletion\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnCompletionDefinition\" }, \"on-fallback\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnFallbackDefinition\" }, \"onFallback\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnFallbackDefinition\" }, \"otherwise\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OtherwiseDefinition\" }, \"pausable\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PausableDefinition\" }, \"pipeline\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PipelineDefinition\" }, \"policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PolicyDefinition\" }, \"poll-enrich\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PollEnrichDefinition\" }, \"pollEnrich\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PollEnrichDefinition\" }, \"process\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessDefinition\" }, \"recipient-list\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RecipientListDefinition\" }, \"recipientList\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RecipientListDefinition\" }, \"remove-header\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemoveHeaderDefinition\" }, \"removeHeader\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemoveHeaderDefinition\" }, \"remove-headers\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemoveHeadersDefinition\" }, \"removeHeaders\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemoveHeadersDefinition\" }, \"remove-properties\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemovePropertiesDefinition\" }, \"removeProperties\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemovePropertiesDefinition\" }, \"remove-property\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemovePropertyDefinition\" }, \"removeProperty\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RemovePropertyDefinition\" }, \"resequence\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ResequenceDefinition\" }, \"resumable\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ResumableDefinition\" }, \"rollback\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RollbackDefinition\" }, \"routing-slip\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RoutingSlipDefinition\" }, \"routingSlip\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RoutingSlipDefinition\" }, \"saga\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SagaDefinition\" }, \"sample\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SamplingDefinition\" }, \"script\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ScriptDefinition\" }, \"set-body\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetBodyDefinition\" }, \"setBody\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetBodyDefinition\" }, \"set-exchange-pattern\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetExchangePatternDefinition\" }, \"setExchangePattern\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetExchangePatternDefinition\" }, \"set-header\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetHeaderDefinition\" }, \"setHeader\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetHeaderDefinition\" }, \"set-property\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetPropertyDefinition\" }, \"setProperty\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SetPropertyDefinition\" }, \"sort\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SortDefinition\" }, \"split\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SplitDefinition\" }, \"step\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.StepDefinition\" }, \"stop\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.StopDefinition\" }, \"threads\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ThreadsDefinition\" }, \"throttle\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ThrottleDefinition\" }, \"throw-exception\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ThrowExceptionDefinition\" }, \"throwException\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ThrowExceptionDefinition\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"to-d\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDynamicDefinition\" }, \"toD\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDynamicDefinition\" }, \"transacted\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TransactedDefinition\" }, \"transform\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TransformDefinition\" }, \"do-try\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TryDefinition\" }, \"doTry\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TryDefinition\" }, \"unmarshal\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.UnmarshalDefinition\" }, \"validate\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ValidateDefinition\" }, \"when\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenDefinition\" }, \"when-skip-send-to-endpoint\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenSkipSendToEndpointDefinition\" }, \"whenSkipSendToEndpoint\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenSkipSendToEndpointDefinition\" }, \"wire-tap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WireTapDefinition\" }, \"wireTap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WireTapDefinition\" }, \"service-call\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ServiceCallDefinition\" }, \"serviceCall\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ServiceCallDefinition\" } } }, \"org.apache.camel.dsl.yaml.deserializers.BeansDeserializer\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.NamedBeanDefinition\" } }, \"org.apache.camel.dsl.yaml.deserializers.ErrorHandlerBuilderDeserializer\" : { \"type\" : \"object\", \"properties\" : { \"dead-letter-channel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.DeadLetterChannelDefinition\" }, \"default-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition\" }, \"jta-transaction-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition\" }, \"no-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.NoErrorHandlerDefinition\" }, \"ref-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.RefErrorHandlerDefinition\" }, \"spring-transaction-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.SpringTransactionErrorHandlerDefinition\" } } }, \"org.apache.camel.dsl.yaml.deserializers.NamedBeanDefinition\" : { \"type\" : \"object\", \"properties\" : { \"name\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"object\" }, \"type\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\", \"type\" ] }, \"org.apache.camel.dsl.yaml.deserializers.OutputAwareFromDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"object\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"uri\" : { \"type\" : \"string\" } }, \"required\" : [ \"steps\", \"uri\" ] }, \"org.apache.camel.dsl.yaml.deserializers.RouteFromDefinitionDeserializer\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.OutputAwareFromDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"object\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"uri\" : { \"type\" : \"string\" } }, \"required\" : [ \"steps\", \"uri\" ] }, \"org.apache.camel.model.AggregateDefinition\" : { \"type\" : \"object\", \"properties\" : { \"aggregate-controller\" : { \"type\" : \"string\" }, \"aggregation-repository\" : { \"type\" : \"string\" }, \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"boolean\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"close-correlation-key-on-completion\" : { \"type\" : \"number\" }, \"complete-all-on-stop\" : { \"type\" : \"boolean\" }, \"completion-from-batch-consumer\" : { \"type\" : \"boolean\" }, \"completion-interval\" : { \"type\" : \"string\" }, \"completion-on-new-correlation-group\" : { \"type\" : \"boolean\" }, \"completion-predicate\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"completion-size\" : { \"type\" : \"number\" }, \"completion-size-expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"completion-timeout\" : { \"type\" : \"string\" }, \"completion-timeout-checker-interval\" : { \"type\" : \"string\" }, \"completion-timeout-expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"correlation-expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"discard-on-aggregation-failure\" : { \"type\" : \"boolean\" }, \"discard-on-completion-timeout\" : { \"type\" : \"boolean\" }, \"eager-check-completion\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"force-completion-on-stop\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-correlation-keys\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"optimistic-lock-retry-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OptimisticLockRetryPolicyDefinition\" }, \"optimistic-locking\" : { \"type\" : \"boolean\" }, \"parallel-processing\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"timeout-checker-executor-service\" : { \"type\" : \"string\" } }, \"required\" : [ \"aggregation-strategy\" ] }, \"org.apache.camel.model.BeanDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"bean-type\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"method\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" }, \"scope\" : { \"type\" : \"string\", \"enum\" : [ \"Singleton\", \"Request\", \"Prototype\" ] } } } ] }, \"org.apache.camel.model.CatchDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"exception\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-when\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenDefinition\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.ChoiceDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"otherwise\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OtherwiseDefinition\" }, \"precondition\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"when\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenDefinition\" } } } }, \"org.apache.camel.model.CircuitBreakerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"configuration\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"fault-tolerance-configuration\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FaultToleranceConfigurationDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-fallback\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnFallbackDefinition\" }, \"resilience4j-configuration\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.Resilience4jConfigurationDefinition\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.ClaimCheckDefinition\" : { \"type\" : \"object\", \"properties\" : { \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"filter\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"key\" : { \"type\" : \"string\" }, \"operation\" : { \"type\" : \"string\", \"enum\" : [ \"Get\", \"GetAndRemove\", \"Set\", \"Push\", \"Pop\" ] } }, \"required\" : [ \"operation\" ] }, \"org.apache.camel.model.ContextScanDefinition\" : { \"type\" : \"object\", \"properties\" : { \"excludes\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"include-non-singletons\" : { \"type\" : \"boolean\" }, \"includes\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } } } }, \"org.apache.camel.model.ConvertBodyDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"charset\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"mandatory\" : { \"type\" : \"boolean\" }, \"type\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"type\" ] }, \"org.apache.camel.model.DataFormatDefinition\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.DelayDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"async-delayed\" : { \"type\" : \"boolean\" }, \"caller-runs-when-rejected\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.DescriptionDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"lang\" : { \"type\" : \"string\" }, \"text\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.DynamicRouterDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"cache-size\" : { \"type\" : \"number\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoints\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"uri-delimiter\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.EnrichDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"aggregate-on-exception\" : { \"type\" : \"boolean\" }, \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"allow-optimised-components\" : { \"type\" : \"boolean\" }, \"cache-size\" : { \"type\" : \"number\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoint\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"share-unit-of-work\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.ErrorHandlerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"dead-letter-channel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.DeadLetterChannelDefinition\" }, \"default-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"jta-transaction-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition\" }, \"no-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.NoErrorHandlerDefinition\" }, \"spring-transaction-error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.errorhandler.SpringTransactionErrorHandlerDefinition\" } } }, \"org.apache.camel.model.ExpressionSubElementDefinition\" : { \"type\" : \"object\", \"properties\" : { \"constant\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ConstantExpression\" }, \"csimple\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.CSimpleExpression\" }, \"datasonnet\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.DatasonnetExpression\" }, \"exchange-property\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExchangePropertyExpression\" }, \"exchangeProperty\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExchangePropertyExpression\" }, \"groovy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.GroovyExpression\" }, \"header\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.HeaderExpression\" }, \"hl7terser\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.Hl7TerserExpression\" }, \"joor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JoorExpression\" }, \"jq\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JqExpression\" }, \"js\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JavaScriptExpression\" }, \"jsonpath\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JsonPathExpression\" }, \"language\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.LanguageExpression\" }, \"method\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.MethodCallExpression\" }, \"mvel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.MvelExpression\" }, \"ognl\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.OgnlExpression\" }, \"python\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.PythonExpression\" }, \"ref\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.RefExpression\" }, \"simple\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.SimpleExpression\" }, \"spel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.SpELExpression\" }, \"tokenize\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.TokenizerExpression\" }, \"xpath\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XPathExpression\" }, \"xquery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XQueryExpression\" }, \"xtokenize\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XMLTokenizerExpression\" } } }, \"org.apache.camel.model.FaultToleranceConfigurationDefinition\" : { \"type\" : \"object\", \"properties\" : { \"bulkhead-enabled\" : { \"type\" : \"boolean\" }, \"bulkhead-executor-service\" : { \"type\" : \"string\" }, \"bulkhead-max-concurrent-calls\" : { \"type\" : \"number\" }, \"bulkhead-waiting-task-queue\" : { \"type\" : \"number\" }, \"circuit-breaker\" : { \"type\" : \"string\" }, \"delay\" : { \"type\" : \"string\" }, \"failure-ratio\" : { \"type\" : \"number\" }, \"id\" : { \"type\" : \"string\" }, \"request-volume-threshold\" : { \"type\" : \"number\" }, \"success-threshold\" : { \"type\" : \"number\" }, \"timeout-duration\" : { \"type\" : \"string\" }, \"timeout-enabled\" : { \"type\" : \"boolean\" }, \"timeout-pool-size\" : { \"type\" : \"number\" }, \"timeout-scheduled-executor-service\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.FilterDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"status-property-name\" : { \"type\" : \"string\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.FinallyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.FromDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"object\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"uri\" : { \"type\" : \"string\" } }, \"required\" : [ \"steps\", \"uri\" ] }, \"org.apache.camel.model.GlobalOptionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"key\" : { \"type\" : \"string\" }, \"value\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\", \"value\" ] }, \"org.apache.camel.model.GlobalOptionsDefinition\" : { \"type\" : \"object\", \"properties\" : { \"global-option\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.GlobalOptionDefinition\" } } } }, \"org.apache.camel.model.IdempotentConsumerDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"completion-eager\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"eager\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"idempotent-repository\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"remove-on-failure\" : { \"type\" : \"boolean\" }, \"skip-duplicate\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } }, \"required\" : [ \"idempotent-repository\" ] }, \"org.apache.camel.model.InOnlyDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"parameters\" : { \"type\" : \"object\" }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.InOutDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"parameters\" : { \"type\" : \"object\" }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.InputTypeDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"urn\" : { \"type\" : \"string\" }, \"validate\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"urn\" ] }, \"org.apache.camel.model.InterceptDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.InterceptFromDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"uri\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.InterceptSendToEndpointDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"after-uri\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"skip-send-to-original-endpoint\" : { \"type\" : \"string\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.KameletDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"name\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"object\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } } ], \"required\" : [ \"name\" ] }, \"org.apache.camel.model.LoadBalanceDefinition\" : { \"type\" : \"object\", \"properties\" : { \"custom-load-balancer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.CustomLoadBalancerDefinition\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"failover\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.FailoverLoadBalancerDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"random\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.RandomLoadBalancerDefinition\" }, \"round-robin\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"sticky\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.StickyLoadBalancerDefinition\" }, \"topic\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.TopicLoadBalancerDefinition\" }, \"weighted\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.loadbalancer.WeightedLoadBalancerDefinition\" } } }, \"org.apache.camel.model.LogDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"log-name\" : { \"type\" : \"string\" }, \"logger\" : { \"type\" : \"string\" }, \"logging-level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"marker\" : { \"type\" : \"string\" }, \"message\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"message\" ] }, \"org.apache.camel.model.LoopDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"break-on-shutdown\" : { \"type\" : \"boolean\" }, \"copy\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"do-while\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.MarshalDefinition\" : { \"type\" : \"object\", \"properties\" : { \"any23\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Any23DataFormat\" }, \"asn1\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ASN1DataFormat\" }, \"avro\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.AvroDataFormat\" }, \"barcode\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BarcodeDataFormat\" }, \"base64\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat\" }, \"bindy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BindyDataFormat\" }, \"cbor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CBORDataFormat\" }, \"crypto\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CryptoDataFormat\" }, \"csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CsvDataFormat\" }, \"custom\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CustomDataFormat\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"fhir-json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirJsonDataFormat\" }, \"fhir-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirXmlDataFormat\" }, \"flatpack\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FlatpackDataFormat\" }, \"grok\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GrokDataFormat\" }, \"gzip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GzipDeflaterDataFormat\" }, \"hl7\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.HL7DataFormat\" }, \"ical\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.IcalDataFormat\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"jackson-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JacksonXMLDataFormat\" }, \"jaxb\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JaxbDataFormat\" }, \"json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonDataFormat\" }, \"json-api\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonApiDataFormat\" }, \"lzf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.LZFDataFormat\" }, \"mime-multipart\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.MimeMultipartDataFormat\" }, \"pgp\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.PGPDataFormat\" }, \"protobuf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ProtobufDataFormat\" }, \"rss\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.RssDataFormat\" }, \"soap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SoapDataFormat\" }, \"swift-mt\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMtDataFormat\" }, \"swift-mx\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMxDataFormat\" }, \"syslog\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SyslogDataFormat\" }, \"tar-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TarFileDataFormat\" }, \"thrift\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ThriftDataFormat\" }, \"tidy-markup\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TidyMarkupDataFormat\" }, \"univocity-csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityCsvDataFormat\" }, \"univocity-fixed\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityFixedDataFormat\" }, \"univocity-tsv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityTsvDataFormat\" }, \"xml-security\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XMLSecurityDataFormat\" }, \"xstream\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XStreamDataFormat\" }, \"yaml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.YAMLDataFormat\" }, \"zip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipDeflaterDataFormat\" }, \"zip-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipFileDataFormat\" } } }, \"org.apache.camel.model.MulticastDefinition\" : { \"type\" : \"object\", \"properties\" : { \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"boolean\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-prepare\" : { \"type\" : \"string\" }, \"parallel-aggregate\" : { \"type\" : \"boolean\" }, \"parallel-processing\" : { \"type\" : \"boolean\" }, \"share-unit-of-work\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"stop-on-exception\" : { \"type\" : \"boolean\" }, \"streaming\" : { \"type\" : \"boolean\" }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.OnCompletionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"mode\" : { \"type\" : \"string\", \"enum\" : [ \"AfterConsumer\", \"BeforeConsumer\" ] }, \"on-complete-only\" : { \"type\" : \"boolean\" }, \"on-failure-only\" : { \"type\" : \"boolean\" }, \"on-when\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenDefinition\" }, \"parallel-processing\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"use-original-message\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.OnExceptionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"continued\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"exception\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"handled\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-exception-occurred-ref\" : { \"type\" : \"string\" }, \"on-redelivery-ref\" : { \"type\" : \"string\" }, \"on-when\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.WhenDefinition\" }, \"redelivery-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RedeliveryPolicyDefinition\" }, \"redelivery-policy-ref\" : { \"type\" : \"string\" }, \"retry-while\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"use-original-body\" : { \"type\" : \"boolean\" }, \"use-original-message\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.OnFallbackDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"fallback-via-network\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.OptimisticLockRetryPolicyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"exponential-back-off\" : { \"type\" : \"boolean\" }, \"maximum-retries\" : { \"type\" : \"number\" }, \"maximum-retry-delay\" : { \"type\" : \"string\" }, \"random-back-off\" : { \"type\" : \"boolean\" }, \"retry-delay\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.OtherwiseDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.OutputDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.OutputTypeDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"urn\" : { \"type\" : \"string\" }, \"validate\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"urn\" ] }, \"org.apache.camel.model.PackageScanDefinition\" : { \"type\" : \"object\", \"properties\" : { \"excludes\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"includes\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"package\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } } } }, \"org.apache.camel.model.PausableDefinition\" : { \"type\" : \"object\", \"properties\" : { \"consumer-listener\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"until-check\" : { \"type\" : \"string\" } }, \"required\" : [ \"consumer-listener\", \"until-check\" ] }, \"org.apache.camel.model.PipelineDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.PolicyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"ref\" : { \"type\" : \"string\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } }, \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.PollEnrichDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"aggregate-on-exception\" : { \"type\" : \"boolean\" }, \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"cache-size\" : { \"type\" : \"number\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoint\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.ProcessDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"ref\" : { \"type\" : \"string\" } }, \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.PropertyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"key\" : { \"type\" : \"string\" }, \"value\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\", \"value\" ] }, \"org.apache.camel.model.PropertyExpressionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"key\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.RecipientListDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"boolean\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"cache-size\" : { \"type\" : \"number\" }, \"delimiter\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoints\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-prepare\" : { \"type\" : \"string\" }, \"parallel-aggregate\" : { \"type\" : \"boolean\" }, \"parallel-processing\" : { \"type\" : \"boolean\" }, \"share-unit-of-work\" : { \"type\" : \"boolean\" }, \"stop-on-exception\" : { \"type\" : \"boolean\" }, \"streaming\" : { \"type\" : \"boolean\" }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.RedeliveryPolicyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allow-redelivery-while-stopping\" : { \"type\" : \"boolean\" }, \"async-delayed-redelivery\" : { \"type\" : \"boolean\" }, \"back-off-multiplier\" : { \"type\" : \"number\" }, \"collision-avoidance-factor\" : { \"type\" : \"number\" }, \"delay-pattern\" : { \"type\" : \"string\" }, \"disable-redelivery\" : { \"type\" : \"boolean\" }, \"exchange-formatter-ref\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"log-continued\" : { \"type\" : \"boolean\" }, \"log-exhausted\" : { \"type\" : \"boolean\" }, \"log-exhausted-message-body\" : { \"type\" : \"boolean\" }, \"log-exhausted-message-history\" : { \"type\" : \"boolean\" }, \"log-handled\" : { \"type\" : \"boolean\" }, \"log-new-exception\" : { \"type\" : \"boolean\" }, \"log-retry-attempted\" : { \"type\" : \"boolean\" }, \"log-retry-stack-trace\" : { \"type\" : \"boolean\" }, \"log-stack-trace\" : { \"type\" : \"boolean\" }, \"maximum-redeliveries\" : { \"type\" : \"number\" }, \"maximum-redelivery-delay\" : { \"type\" : \"string\" }, \"redelivery-delay\" : { \"type\" : \"string\" }, \"retries-exhausted-log-level\" : { \"type\" : \"string\" }, \"retry-attempted-log-interval\" : { \"type\" : \"number\" }, \"retry-attempted-log-level\" : { \"type\" : \"string\" }, \"use-collision-avoidance\" : { \"type\" : \"boolean\" }, \"use-exponential-back-off\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.RemoveHeaderDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"name\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"name\" ] }, \"org.apache.camel.model.RemoveHeadersDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"exclude-pattern\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"pattern\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"pattern\" ] }, \"org.apache.camel.model.RemovePropertiesDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"exclude-pattern\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"pattern\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"pattern\" ] }, \"org.apache.camel.model.RemovePropertyDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"name\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"name\" ] }, \"org.apache.camel.model.ResequenceDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"batch-config\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.config.BatchResequencerConfig\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"stream-config\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.config.StreamResequencerConfig\" } }, \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.Resilience4jConfigurationDefinition\" : { \"type\" : \"object\", \"properties\" : { \"automatic-transition-from-open-to-half-open-enabled\" : { \"type\" : \"boolean\" }, \"circuit-breaker\" : { \"type\" : \"string\" }, \"config\" : { \"type\" : \"string\" }, \"failure-rate-threshold\" : { \"type\" : \"number\" }, \"id\" : { \"type\" : \"string\" }, \"minimum-number-of-calls\" : { \"type\" : \"number\" }, \"permitted-number-of-calls-in-half-open-state\" : { \"type\" : \"number\" }, \"sliding-window-size\" : { \"type\" : \"number\" }, \"sliding-window-type\" : { \"type\" : \"string\", \"enum\" : [ \"TIME_BASED\", \"COUNT_BASED\" ] }, \"slow-call-duration-threshold\" : { \"type\" : \"number\" }, \"slow-call-rate-threshold\" : { \"type\" : \"number\" }, \"throw-exception-when-half-open-or-open-state\" : { \"type\" : \"boolean\" }, \"wait-duration-in-open-state\" : { \"type\" : \"number\" }, \"writable-stack-trace-enabled\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.RestContextRefDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.ResumableDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"intermittent\" : { \"type\" : \"boolean\" }, \"resume-strategy\" : { \"type\" : \"string\" } }, \"required\" : [ \"resume-strategy\" ] }, \"org.apache.camel.model.RollbackDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"mark-rollback-only\" : { \"type\" : \"boolean\" }, \"mark-rollback-only-last\" : { \"type\" : \"boolean\" }, \"message\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.RouteBuilderDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.RouteConfigurationContextRefDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.RouteConfigurationDefinition\" : { \"type\" : \"object\", \"properties\" : { \"error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ErrorHandlerDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"intercept\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptDefinition\" } }, \"intercept-from\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptFromDefinition\" } }, \"intercept-send-to-endpoint\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.InterceptSendToEndpointDefinition\" } }, \"on-completion\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnCompletionDefinition\" } }, \"on-exception\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnExceptionDefinition\" } }, \"precondition\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.RouteContextRefDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.RouteDefinition\" : { \"type\" : \"object\", \"properties\" : { \"auto-startup\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"from\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FromDefinition\" }, \"group\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"log-mask\" : { \"type\" : \"boolean\" }, \"message-history\" : { \"type\" : \"boolean\" }, \"node-prefix-id\" : { \"type\" : \"string\" }, \"precondition\" : { \"type\" : \"string\" }, \"route-configuration-id\" : { \"type\" : \"string\" }, \"route-policy\" : { \"type\" : \"string\" }, \"startup-order\" : { \"type\" : \"number\" }, \"stream-caching\" : { \"type\" : \"boolean\" }, \"trace\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"from\" ] }, \"org.apache.camel.model.RouteTemplateBeanDefinition\" : { \"type\" : \"object\", \"properties\" : { \"bean-type\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"object\" }, \"property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"script\" : { \"type\" : \"string\" }, \"type\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\", \"type\" ] }, \"org.apache.camel.model.RouteTemplateDefinition\" : { \"type\" : \"object\", \"properties\" : { \"beans\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.NamedBeanDefinition\" } }, \"from\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FromDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteTemplateParameterDefinition\" } }, \"route\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteDefinition\" } }, \"required\" : [ \"id\" ] }, \"org.apache.camel.model.RouteTemplateParameterDefinition\" : { \"type\" : \"object\", \"properties\" : { \"default-value\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" }, \"required\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"name\" ] }, \"org.apache.camel.model.RoutingSlipDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"cache-size\" : { \"type\" : \"number\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoints\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"uri-delimiter\" : { \"type\" : \"string\" } } } ], \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ] }, \"org.apache.camel.model.SagaActionUriDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"parameters\" : { \"type\" : \"object\" }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.SagaDefinition\" : { \"type\" : \"object\", \"properties\" : { \"compensation\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SagaActionUriDefinition\" }, \"completion\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.SagaActionUriDefinition\" }, \"completion-mode\" : { \"type\" : \"string\", \"enum\" : [ \"AUTO\", \"MANUAL\" ] }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"option\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyExpressionDefinition\" } }, \"propagation\" : { \"type\" : \"string\", \"enum\" : [ \"REQUIRED\", \"REQUIRES_NEW\", \"MANDATORY\", \"SUPPORTS\", \"NOT_SUPPORTED\", \"NEVER\" ] }, \"saga-service\" : { \"type\" : \"string\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.SamplingDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"message-frequency\" : { \"type\" : \"number\" }, \"sample-period\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.ScriptDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.SetBodyDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.SetExchangePatternDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] } } } ], \"required\" : [ \"pattern\" ] }, \"org.apache.camel.model.SetHeaderDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"name\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\" ] }, \"org.apache.camel.model.SetPropertyDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"name\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\" ] }, \"org.apache.camel.model.SortDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"comparator\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.SplitDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"aggregation-strategy\" : { \"type\" : \"string\" }, \"aggregation-strategy-method-allow-null\" : { \"type\" : \"boolean\" }, \"aggregation-strategy-method-name\" : { \"type\" : \"string\" }, \"delimiter\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-prepare\" : { \"type\" : \"string\" }, \"parallel-aggregate\" : { \"type\" : \"boolean\" }, \"parallel-processing\" : { \"type\" : \"boolean\" }, \"share-unit-of-work\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } }, \"stop-on-exception\" : { \"type\" : \"boolean\" }, \"streaming\" : { \"type\" : \"boolean\" }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.StepDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.StopDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.TemplatedRouteBeanDefinition\" : { \"type\" : \"object\", \"properties\" : { \"bean-type\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"object\" }, \"property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"script\" : { \"type\" : \"string\" }, \"type\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\", \"type\" ] }, \"org.apache.camel.model.TemplatedRouteDefinition\" : { \"type\" : \"object\", \"properties\" : { \"beans\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.NamedBeanDefinition\" } }, \"parameters\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TemplatedRouteParameterDefinition\" } }, \"prefix-id\" : { \"type\" : \"string\" }, \"route-id\" : { \"type\" : \"string\" }, \"route-template-ref\" : { \"type\" : \"string\" } }, \"required\" : [ \"route-template-ref\" ] }, \"org.apache.camel.model.TemplatedRouteParameterDefinition\" : { \"type\" : \"object\", \"properties\" : { \"name\" : { \"type\" : \"string\" }, \"value\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\", \"value\" ] }, \"org.apache.camel.model.ThreadPoolProfileDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allow-core-thread-time-out\" : { \"type\" : \"boolean\" }, \"default-profile\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"keep-alive-time\" : { \"type\" : \"number\" }, \"max-pool-size\" : { \"type\" : \"number\" }, \"max-queue-size\" : { \"type\" : \"number\" }, \"pool-size\" : { \"type\" : \"number\" }, \"rejected-policy\" : { \"type\" : \"string\", \"enum\" : [ \"Abort\", \"CallerRuns\", \"DiscardOldest\", \"Discard\" ] }, \"time-unit\" : { \"type\" : \"string\", \"enum\" : [ \"NANOSECONDS\", \"MICROSECONDS\", \"MILLISECONDS\", \"SECONDS\", \"MINUTES\", \"HOURS\", \"DAYS\" ] } } }, \"org.apache.camel.model.ThreadsDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allow-core-thread-time-out\" : { \"type\" : \"boolean\" }, \"caller-runs-when-rejected\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"keep-alive-time\" : { \"type\" : \"number\" }, \"max-pool-size\" : { \"type\" : \"number\" }, \"max-queue-size\" : { \"type\" : \"number\" }, \"pool-size\" : { \"type\" : \"number\" }, \"rejected-policy\" : { \"type\" : \"string\", \"enum\" : [ \"Abort\", \"CallerRuns\", \"DiscardOldest\", \"Discard\" ] }, \"thread-name\" : { \"type\" : \"string\" }, \"time-unit\" : { \"type\" : \"string\", \"enum\" : [ \"NANOSECONDS\", \"MICROSECONDS\", \"MILLISECONDS\", \"SECONDS\", \"MINUTES\", \"HOURS\", \"DAYS\" ] } } }, \"org.apache.camel.model.ThrottleDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"async-delayed\" : { \"type\" : \"boolean\" }, \"caller-runs-when-rejected\" : { \"type\" : \"boolean\" }, \"correlation-expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"reject-execution\" : { \"type\" : \"boolean\" }, \"time-period-millis\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.ThrowExceptionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"exception-type\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"message\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.ToDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"parameters\" : { \"type\" : \"object\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.ToDynamicDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"allow-optimised-components\" : { \"type\" : \"boolean\" }, \"auto-start-components\" : { \"type\" : \"boolean\" }, \"cache-size\" : { \"type\" : \"number\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoint\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"parameters\" : { \"type\" : \"object\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] }, \"uri\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.TransactedDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"ref\" : { \"type\" : \"string\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.TransformDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.TryDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"do-catch\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.CatchDefinition\" } }, \"do-finally\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.FinallyDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.UnmarshalDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allow-null-body\" : { \"type\" : \"boolean\" }, \"any23\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Any23DataFormat\" }, \"asn1\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ASN1DataFormat\" }, \"avro\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.AvroDataFormat\" }, \"barcode\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BarcodeDataFormat\" }, \"base64\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat\" }, \"bindy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BindyDataFormat\" }, \"cbor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CBORDataFormat\" }, \"crypto\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CryptoDataFormat\" }, \"csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CsvDataFormat\" }, \"custom\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CustomDataFormat\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"fhir-json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirJsonDataFormat\" }, \"fhir-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirXmlDataFormat\" }, \"flatpack\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FlatpackDataFormat\" }, \"grok\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GrokDataFormat\" }, \"gzip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GzipDeflaterDataFormat\" }, \"hl7\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.HL7DataFormat\" }, \"ical\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.IcalDataFormat\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"jackson-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JacksonXMLDataFormat\" }, \"jaxb\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JaxbDataFormat\" }, \"json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonDataFormat\" }, \"json-api\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonApiDataFormat\" }, \"lzf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.LZFDataFormat\" }, \"mime-multipart\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.MimeMultipartDataFormat\" }, \"pgp\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.PGPDataFormat\" }, \"protobuf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ProtobufDataFormat\" }, \"rss\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.RssDataFormat\" }, \"soap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SoapDataFormat\" }, \"swift-mt\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMtDataFormat\" }, \"swift-mx\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMxDataFormat\" }, \"syslog\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SyslogDataFormat\" }, \"tar-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TarFileDataFormat\" }, \"thrift\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ThriftDataFormat\" }, \"tidy-markup\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TidyMarkupDataFormat\" }, \"univocity-csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityCsvDataFormat\" }, \"univocity-fixed\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityFixedDataFormat\" }, \"univocity-tsv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityTsvDataFormat\" }, \"xml-security\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XMLSecurityDataFormat\" }, \"xstream\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XStreamDataFormat\" }, \"yaml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.YAMLDataFormat\" }, \"zip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipDeflaterDataFormat\" }, \"zip-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipFileDataFormat\" } } }, \"org.apache.camel.model.ValidateDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"predicate-exception-factory\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.ValueDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"value\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.WhenDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.WhenSkipSendToEndpointDefinition\" : { \"type\" : \"object\", \"anyOf\" : [ { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" } ], \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"steps\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ProcessorDefinition\" } } } }, \"org.apache.camel.model.WireTapDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allow-optimised-components\" : { \"type\" : \"boolean\" }, \"auto-start-components\" : { \"type\" : \"boolean\" }, \"cache-size\" : { \"type\" : \"number\" }, \"copy\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"dynamic-uri\" : { \"type\" : \"boolean\" }, \"executor-service\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-invalid-endpoint\" : { \"type\" : \"boolean\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"on-prepare\" : { \"type\" : \"string\" }, \"parameters\" : { \"type\" : \"object\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] }, \"uri\" : { \"type\" : \"string\" } }, \"required\" : [ \"uri\" ] }, \"org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"servers\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } } } }, \"org.apache.camel.model.cloud.CachingServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"combined-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CombinedServiceCallServiceDiscoveryConfiguration\" }, \"consul-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ConsulServiceCallServiceDiscoveryConfiguration\" }, \"dns-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DnsServiceCallServiceDiscoveryConfiguration\" }, \"id\" : { \"type\" : \"string\" }, \"kubernetes-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.KubernetesServiceCallServiceDiscoveryConfiguration\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"static-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration\" }, \"timeout\" : { \"type\" : \"number\" }, \"units\" : { \"type\" : \"string\", \"enum\" : [ \"NANOSECONDS\", \"MICROSECONDS\", \"MILLISECONDS\", \"SECONDS\", \"MINUTES\", \"HOURS\", \"DAYS\" ] } } }, \"org.apache.camel.model.cloud.CombinedServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"caching-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CachingServiceCallServiceDiscoveryConfiguration\" }, \"consul-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ConsulServiceCallServiceDiscoveryConfiguration\" }, \"dns-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DnsServiceCallServiceDiscoveryConfiguration\" }, \"id\" : { \"type\" : \"string\" }, \"kubernetes-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.KubernetesServiceCallServiceDiscoveryConfiguration\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"static-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration\" } } }, \"org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"blacklist-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration\" }, \"custom-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CustomServiceCallServiceFilterConfiguration\" }, \"healthy-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.HealthyServiceCallServiceFilterConfiguration\" }, \"id\" : { \"type\" : \"string\" }, \"pass-through-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.PassThroughServiceCallServiceFilterConfiguration\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ConsulServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"acl-token\" : { \"type\" : \"string\" }, \"block-seconds\" : { \"type\" : \"number\" }, \"connect-timeout-millis\" : { \"type\" : \"number\" }, \"datacenter\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"password\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"read-timeout-millis\" : { \"type\" : \"number\" }, \"url\" : { \"type\" : \"string\" }, \"user-name\" : { \"type\" : \"string\" }, \"write-timeout-millis\" : { \"type\" : \"number\" } } }, \"org.apache.camel.model.cloud.CustomServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"ref\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.cloud.DefaultServiceCallServiceLoadBalancerConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.DnsServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"domain\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"proto\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.cloud.HealthyServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.KubernetesServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"api-version\" : { \"type\" : \"string\" }, \"ca-cert-data\" : { \"type\" : \"string\" }, \"ca-cert-file\" : { \"type\" : \"string\" }, \"client-cert-data\" : { \"type\" : \"string\" }, \"client-cert-file\" : { \"type\" : \"string\" }, \"client-key-algo\" : { \"type\" : \"string\" }, \"client-key-data\" : { \"type\" : \"string\" }, \"client-key-file\" : { \"type\" : \"string\" }, \"client-key-passphrase\" : { \"type\" : \"string\" }, \"dns-domain\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"lookup\" : { \"type\" : \"string\", \"enum\" : [ \"environment\", \"dns\", \"client\" ] }, \"master-url\" : { \"type\" : \"string\" }, \"namespace\" : { \"type\" : \"string\" }, \"oauth-token\" : { \"type\" : \"string\" }, \"password\" : { \"type\" : \"string\" }, \"port-name\" : { \"type\" : \"string\" }, \"port-protocol\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"trust-certs\" : { \"type\" : \"boolean\" }, \"username\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.cloud.PassThroughServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ServiceCallConfigurationDefinition\" : { \"type\" : \"object\", \"properties\" : { \"blacklist-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration\" }, \"caching-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CachingServiceCallServiceDiscoveryConfiguration\" }, \"combined-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CombinedServiceCallServiceDiscoveryConfiguration\" }, \"combined-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration\" }, \"component\" : { \"type\" : \"string\" }, \"consul-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ConsulServiceCallServiceDiscoveryConfiguration\" }, \"custom-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CustomServiceCallServiceFilterConfiguration\" }, \"default-load-balancer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DefaultServiceCallServiceLoadBalancerConfiguration\" }, \"dns-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DnsServiceCallServiceDiscoveryConfiguration\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ServiceCallExpressionConfiguration\" }, \"expression-ref\" : { \"type\" : \"string\" }, \"healthy-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.HealthyServiceCallServiceFilterConfiguration\" }, \"id\" : { \"type\" : \"string\" }, \"kubernetes-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.KubernetesServiceCallServiceDiscoveryConfiguration\" }, \"load-balancer-ref\" : { \"type\" : \"string\" }, \"pass-through-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.PassThroughServiceCallServiceFilterConfiguration\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] }, \"service-chooser-ref\" : { \"type\" : \"string\" }, \"service-discovery-ref\" : { \"type\" : \"string\" }, \"service-filter-ref\" : { \"type\" : \"string\" }, \"static-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration\" }, \"uri\" : { \"type\" : \"string\" }, \"zookeeper-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ZooKeeperServiceCallServiceDiscoveryConfiguration\" } } }, \"org.apache.camel.model.cloud.ServiceCallDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"blacklist-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration\" }, \"caching-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CachingServiceCallServiceDiscoveryConfiguration\" }, \"combined-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CombinedServiceCallServiceDiscoveryConfiguration\" }, \"combined-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration\" }, \"component\" : { \"type\" : \"string\" }, \"configuration-ref\" : { \"type\" : \"string\" }, \"consul-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ConsulServiceCallServiceDiscoveryConfiguration\" }, \"custom-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.CustomServiceCallServiceFilterConfiguration\" }, \"default-load-balancer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DefaultServiceCallServiceLoadBalancerConfiguration\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"dns-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.DnsServiceCallServiceDiscoveryConfiguration\" }, \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ServiceCallExpressionConfiguration\" }, \"expression-ref\" : { \"type\" : \"string\" }, \"healthy-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.HealthyServiceCallServiceFilterConfiguration\" }, \"id\" : { \"type\" : \"string\" }, \"inherit-error-handler\" : { \"type\" : \"boolean\" }, \"kubernetes-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.KubernetesServiceCallServiceDiscoveryConfiguration\" }, \"load-balancer-ref\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" }, \"pass-through-service-filter\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.PassThroughServiceCallServiceFilterConfiguration\" }, \"pattern\" : { \"type\" : \"string\", \"enum\" : [ \"InOnly\", \"InOut\", \"InOptionalOut\" ] }, \"service-chooser-ref\" : { \"type\" : \"string\" }, \"service-discovery-ref\" : { \"type\" : \"string\" }, \"service-filter-ref\" : { \"type\" : \"string\" }, \"static-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration\" }, \"uri\" : { \"type\" : \"string\" }, \"zookeeper-service-discovery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.cloud.ZooKeeperServiceCallServiceDiscoveryConfiguration\" } } } ], \"required\" : [ \"name\" ] }, \"org.apache.camel.model.cloud.ServiceCallExpressionConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"expression-type\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"host-header\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"port-header\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ServiceCallServiceChooserConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ServiceCallServiceFilterConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.ServiceCallServiceLoadBalancerConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } } } }, \"org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"servers\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } } } }, \"org.apache.camel.model.cloud.ZooKeeperServiceCallServiceDiscoveryConfiguration\" : { \"type\" : \"object\", \"properties\" : { \"base-path\" : { \"type\" : \"string\" }, \"connection-timeout\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"namespace\" : { \"type\" : \"string\" }, \"nodes\" : { \"type\" : \"string\" }, \"properties\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"reconnect-base-sleep-time\" : { \"type\" : \"string\" }, \"reconnect-max-retries\" : { \"type\" : \"string\" }, \"reconnect-max-sleep-time\" : { \"type\" : \"string\" }, \"session-timeout\" : { \"type\" : \"string\" } }, \"required\" : [ \"base-path\", \"nodes\" ] }, \"org.apache.camel.model.config.BatchResequencerConfig\" : { \"type\" : \"object\", \"properties\" : { \"allow-duplicates\" : { \"type\" : \"boolean\" }, \"batch-size\" : { \"type\" : \"number\" }, \"batch-timeout\" : { \"type\" : \"string\" }, \"ignore-invalid-exchanges\" : { \"type\" : \"boolean\" }, \"reverse\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.config.StreamResequencerConfig\" : { \"type\" : \"object\", \"properties\" : { \"capacity\" : { \"type\" : \"number\" }, \"comparator\" : { \"type\" : \"string\" }, \"delivery-attempt-interval\" : { \"type\" : \"string\" }, \"ignore-invalid-exchanges\" : { \"type\" : \"boolean\" }, \"reject-old\" : { \"type\" : \"boolean\" }, \"timeout\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.ASN1DataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"using-iterator\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.dataformat.Any23DataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"base-uri\" : { \"type\" : \"string\" }, \"configuration\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"extractors\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"id\" : { \"type\" : \"string\" }, \"output-format\" : { \"type\" : \"string\", \"enum\" : [ \"NTRIPLES\", \"TURTLE\", \"NQUADS\", \"RDFXML\", \"JSONLD\", \"RDFJSON\", \"RDF4JMODEL\" ] } } } ] }, \"org.apache.camel.model.dataformat.AvroDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"allow-jms-type\" : { \"type\" : \"boolean\" }, \"allow-unmarshall-type\" : { \"type\" : \"boolean\" }, \"auto-discover-object-mapper\" : { \"type\" : \"boolean\" }, \"auto-discover-schema-resolver\" : { \"type\" : \"boolean\" }, \"collection-type\" : { \"type\" : \"string\" }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"disable-features\" : { \"type\" : \"string\" }, \"enable-features\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"include\" : { \"type\" : \"string\" }, \"instance-class-name\" : { \"type\" : \"string\" }, \"json-view\" : { \"type\" : \"string\" }, \"library\" : { \"type\" : \"string\", \"enum\" : [ \"ApacheAvro\", \"Jackson\" ] }, \"module-class-names\" : { \"type\" : \"string\" }, \"module-refs\" : { \"type\" : \"string\" }, \"object-mapper\" : { \"type\" : \"string\" }, \"schema-resolver\" : { \"type\" : \"string\" }, \"timezone\" : { \"type\" : \"string\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-default-object-mapper\" : { \"type\" : \"boolean\" }, \"use-list\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.dataformat.BarcodeDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"barcode-format\" : { \"type\" : \"string\" }, \"height\" : { \"type\" : \"number\" }, \"id\" : { \"type\" : \"string\" }, \"image-type\" : { \"type\" : \"string\" }, \"width\" : { \"type\" : \"number\" } } }, \"org.apache.camel.model.dataformat.Base64DataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"line-length\" : { \"type\" : \"number\" }, \"line-separator\" : { \"type\" : \"string\" }, \"url-safe\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.BindyDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-empty-stream\" : { \"type\" : \"boolean\" }, \"class-type\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"locale\" : { \"type\" : \"string\" }, \"type\" : { \"type\" : \"string\", \"enum\" : [ \"Csv\", \"Fixed\", \"KeyValue\" ] }, \"unwrap-single-instance\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"type\" ] }, \"org.apache.camel.model.dataformat.CBORDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-jms-type\" : { \"type\" : \"boolean\" }, \"allow-unmarshall-type\" : { \"type\" : \"boolean\" }, \"collection-type\" : { \"type\" : \"string\" }, \"disable-features\" : { \"type\" : \"string\" }, \"enable-features\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"object-mapper\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-default-object-mapper\" : { \"type\" : \"boolean\" }, \"use-list\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.CryptoDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"algorithm\" : { \"type\" : \"string\" }, \"algorithm-parameter-ref\" : { \"type\" : \"string\" }, \"buffer-size\" : { \"type\" : \"number\" }, \"crypto-provider\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"init-vector-ref\" : { \"type\" : \"string\" }, \"inline\" : { \"type\" : \"boolean\" }, \"key-ref\" : { \"type\" : \"string\" }, \"mac-algorithm\" : { \"type\" : \"string\" }, \"should-append-hmac\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.CsvDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"allow-missing-column-names\" : { \"type\" : \"boolean\" }, \"capture-header-record\" : { \"type\" : \"boolean\" }, \"comment-marker\" : { \"type\" : \"string\" }, \"comment-marker-disabled\" : { \"type\" : \"boolean\" }, \"delimiter\" : { \"type\" : \"string\" }, \"escape\" : { \"type\" : \"string\" }, \"escape-disabled\" : { \"type\" : \"boolean\" }, \"format-name\" : { \"type\" : \"string\", \"enum\" : [ \"DEFAULT\", \"EXCEL\", \"INFORMIX_UNLOAD\", \"INFORMIX_UNLOAD_CSV\", \"MYSQL\", \"RFC4180\" ] }, \"format-ref\" : { \"type\" : \"string\" }, \"header\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"header-disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-empty-lines\" : { \"type\" : \"boolean\" }, \"ignore-header-case\" : { \"type\" : \"boolean\" }, \"ignore-surrounding-spaces\" : { \"type\" : \"boolean\" }, \"lazy-load\" : { \"type\" : \"boolean\" }, \"marshaller-factory-ref\" : { \"type\" : \"string\" }, \"null-string\" : { \"type\" : \"string\" }, \"null-string-disabled\" : { \"type\" : \"boolean\" }, \"quote\" : { \"type\" : \"string\" }, \"quote-disabled\" : { \"type\" : \"boolean\" }, \"quote-mode\" : { \"type\" : \"string\", \"enum\" : [ \"ALL\", \"ALL_NON_NULL\", \"MINIMAL\", \"NON_NUMERIC\", \"NONE\" ] }, \"record-converter-ref\" : { \"type\" : \"string\" }, \"record-separator\" : { \"type\" : \"string\" }, \"record-separator-disabled\" : { \"type\" : \"string\" }, \"skip-header-record\" : { \"type\" : \"boolean\" }, \"trailing-delimiter\" : { \"type\" : \"boolean\" }, \"trim\" : { \"type\" : \"boolean\" }, \"use-maps\" : { \"type\" : \"boolean\" }, \"use-ordered-maps\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.dataformat.CustomDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.dataformat.DataFormatsDefinition\" : { \"type\" : \"object\", \"properties\" : { \"any23\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Any23DataFormat\" }, \"asn1\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ASN1DataFormat\" }, \"avro\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.AvroDataFormat\" }, \"barcode\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BarcodeDataFormat\" }, \"base64\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat\" }, \"bindy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BindyDataFormat\" }, \"cbor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CBORDataFormat\" }, \"crypto\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CryptoDataFormat\" }, \"csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CsvDataFormat\" }, \"custom\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CustomDataFormat\" }, \"fhir-json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirJsonDataFormat\" }, \"fhir-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirXmlDataFormat\" }, \"flatpack\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FlatpackDataFormat\" }, \"grok\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GrokDataFormat\" }, \"gzip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GzipDeflaterDataFormat\" }, \"hl7\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.HL7DataFormat\" }, \"ical\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.IcalDataFormat\" }, \"jackson-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JacksonXMLDataFormat\" }, \"jaxb\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JaxbDataFormat\" }, \"json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonDataFormat\" }, \"json-api\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonApiDataFormat\" }, \"lzf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.LZFDataFormat\" }, \"mime-multipart\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.MimeMultipartDataFormat\" }, \"pgp\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.PGPDataFormat\" }, \"protobuf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ProtobufDataFormat\" }, \"rss\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.RssDataFormat\" }, \"soap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SoapDataFormat\" }, \"swift-mt\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMtDataFormat\" }, \"swift-mx\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMxDataFormat\" }, \"syslog\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SyslogDataFormat\" }, \"tar-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TarFileDataFormat\" }, \"thrift\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ThriftDataFormat\" }, \"tidy-markup\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TidyMarkupDataFormat\" }, \"univocity-csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityCsvDataFormat\" }, \"univocity-fixed\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityFixedDataFormat\" }, \"univocity-tsv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityTsvDataFormat\" }, \"xml-security\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XMLSecurityDataFormat\" }, \"xstream\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XStreamDataFormat\" }, \"yaml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.YAMLDataFormat\" }, \"zip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipDeflaterDataFormat\" }, \"zip-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipFileDataFormat\" } } }, \"org.apache.camel.model.dataformat.FhirJsonDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"content-type-header\" : { \"type\" : \"boolean\" }, \"dont-encode-elements\" : { \"type\" : \"string\" }, \"dont-strip-versions-from-references-at-paths\" : { \"type\" : \"string\" }, \"encode-elements\" : { \"type\" : \"string\" }, \"encode-elements-applies-to-child-resources-only\" : { \"type\" : \"boolean\" }, \"fhir-context\" : { \"type\" : \"string\" }, \"fhir-version\" : { \"type\" : \"string\", \"enum\" : [ \"DSTU2\", \"DSTU2_HL7ORG\", \"DSTU2_1\", \"DSTU3\", \"R4\", \"R5\" ] }, \"force-resource-id\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"omit-resource-id\" : { \"type\" : \"boolean\" }, \"override-resource-id-with-bundle-entry-full-url\" : { \"type\" : \"boolean\" }, \"parser-error-handler\" : { \"type\" : \"string\" }, \"parser-options\" : { \"type\" : \"string\" }, \"prefer-types\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"server-base-url\" : { \"type\" : \"string\" }, \"strip-versions-from-references\" : { \"type\" : \"boolean\" }, \"summary-mode\" : { \"type\" : \"boolean\" }, \"suppress-narratives\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.FhirXmlDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"content-type-header\" : { \"type\" : \"boolean\" }, \"dont-encode-elements\" : { \"type\" : \"string\" }, \"dont-strip-versions-from-references-at-paths\" : { \"type\" : \"string\" }, \"encode-elements\" : { \"type\" : \"string\" }, \"encode-elements-applies-to-child-resources-only\" : { \"type\" : \"boolean\" }, \"fhir-context\" : { \"type\" : \"string\" }, \"fhir-version\" : { \"type\" : \"string\", \"enum\" : [ \"DSTU2\", \"DSTU2_HL7ORG\", \"DSTU2_1\", \"DSTU3\", \"R4\", \"R5\" ] }, \"force-resource-id\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"omit-resource-id\" : { \"type\" : \"boolean\" }, \"override-resource-id-with-bundle-entry-full-url\" : { \"type\" : \"boolean\" }, \"parser-error-handler\" : { \"type\" : \"string\" }, \"parser-options\" : { \"type\" : \"string\" }, \"prefer-types\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"server-base-url\" : { \"type\" : \"string\" }, \"strip-versions-from-references\" : { \"type\" : \"boolean\" }, \"summary-mode\" : { \"type\" : \"boolean\" }, \"suppress-narratives\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.FlatpackDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-short-lines\" : { \"type\" : \"boolean\" }, \"definition\" : { \"type\" : \"string\" }, \"delimiter\" : { \"type\" : \"string\" }, \"fixed\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-extra-columns\" : { \"type\" : \"boolean\" }, \"ignore-first-record\" : { \"type\" : \"boolean\" }, \"parser-factory-ref\" : { \"type\" : \"string\" }, \"text-qualifier\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.GrokDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-multiple-matches-per-line\" : { \"type\" : \"boolean\" }, \"flattened\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"named-only\" : { \"type\" : \"boolean\" }, \"pattern\" : { \"type\" : \"string\" } }, \"required\" : [ \"pattern\" ] }, \"org.apache.camel.model.dataformat.GzipDeflaterDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.HL7DataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"validate\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.IcalDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"validating\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.JacksonXMLDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-jms-type\" : { \"type\" : \"boolean\" }, \"allow-unmarshall-type\" : { \"type\" : \"boolean\" }, \"collection-type\" : { \"type\" : \"string\" }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"disable-features\" : { \"type\" : \"string\" }, \"enable-features\" : { \"type\" : \"string\" }, \"enable-jaxb-annotation-module\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"include\" : { \"type\" : \"string\" }, \"json-view\" : { \"type\" : \"string\" }, \"module-class-names\" : { \"type\" : \"string\" }, \"module-refs\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"timezone\" : { \"type\" : \"string\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-list\" : { \"type\" : \"boolean\" }, \"xml-mapper\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.JaxbDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"content-type-header\" : { \"type\" : \"boolean\" }, \"context-path\" : { \"type\" : \"string\" }, \"context-path-is-class-name\" : { \"type\" : \"boolean\" }, \"encoding\" : { \"type\" : \"string\" }, \"filter-non-xml-chars\" : { \"type\" : \"boolean\" }, \"fragment\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-jaxb-element\" : { \"type\" : \"boolean\" }, \"jaxb-provider-properties\" : { \"type\" : \"string\" }, \"must-be-jaxb-element\" : { \"type\" : \"boolean\" }, \"namespace-prefix-ref\" : { \"type\" : \"string\" }, \"no-namespace-schema-location\" : { \"type\" : \"string\" }, \"object-factory\" : { \"type\" : \"boolean\" }, \"part-class\" : { \"type\" : \"string\" }, \"part-namespace\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"schema\" : { \"type\" : \"string\" }, \"schema-location\" : { \"type\" : \"string\" }, \"schema-severity-level\" : { \"type\" : \"string\", \"enum\" : [ \"0\", \"1\", \"2\" ] }, \"xml-stream-writer-wrapper\" : { \"type\" : \"string\" } }, \"required\" : [ \"context-path\" ] }, \"org.apache.camel.model.dataformat.JsonApiDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"data-format-types\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"main-format-type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.JsonDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-jms-type\" : { \"type\" : \"boolean\" }, \"allow-unmarshall-type\" : { \"type\" : \"boolean\" }, \"auto-discover-object-mapper\" : { \"type\" : \"boolean\" }, \"auto-discover-schema-resolver\" : { \"type\" : \"boolean\" }, \"collection-type\" : { \"type\" : \"string\" }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"disable-features\" : { \"type\" : \"string\" }, \"drop-root-node\" : { \"type\" : \"boolean\" }, \"enable-features\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"include\" : { \"type\" : \"string\" }, \"json-view\" : { \"type\" : \"string\" }, \"library\" : { \"type\" : \"string\", \"enum\" : [ \"Fastjson\", \"Gson\", \"Jackson\", \"Johnzon\", \"Jsonb\", \"XStream\" ] }, \"module-class-names\" : { \"type\" : \"string\" }, \"module-refs\" : { \"type\" : \"string\" }, \"naming-strategy\" : { \"type\" : \"string\" }, \"object-mapper\" : { \"type\" : \"string\" }, \"permissions\" : { \"type\" : \"string\" }, \"pretty-print\" : { \"type\" : \"boolean\" }, \"schema-resolver\" : { \"type\" : \"string\" }, \"timezone\" : { \"type\" : \"string\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-default-object-mapper\" : { \"type\" : \"boolean\" }, \"use-list\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.LZFDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"using-parallel-compression\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.MimeMultipartDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"binary-content\" : { \"type\" : \"boolean\" }, \"headers-inline\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"include-headers\" : { \"type\" : \"string\" }, \"multipart-sub-type\" : { \"type\" : \"string\" }, \"multipart-without-attachment\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.PGPDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"algorithm\" : { \"type\" : \"number\" }, \"armored\" : { \"type\" : \"boolean\" }, \"compression-algorithm\" : { \"type\" : \"number\" }, \"hash-algorithm\" : { \"type\" : \"number\" }, \"id\" : { \"type\" : \"string\" }, \"integrity\" : { \"type\" : \"boolean\" }, \"key-file-name\" : { \"type\" : \"string\" }, \"key-userid\" : { \"type\" : \"string\" }, \"password\" : { \"type\" : \"string\" }, \"provider\" : { \"type\" : \"string\" }, \"signature-key-file-name\" : { \"type\" : \"string\" }, \"signature-key-ring\" : { \"type\" : \"string\" }, \"signature-key-userid\" : { \"type\" : \"string\" }, \"signature-password\" : { \"type\" : \"string\" }, \"signature-verification-option\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.ProtobufDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"allow-jms-type\" : { \"type\" : \"boolean\" }, \"allow-unmarshall-type\" : { \"type\" : \"boolean\" }, \"auto-discover-object-mapper\" : { \"type\" : \"boolean\" }, \"auto-discover-schema-resolver\" : { \"type\" : \"boolean\" }, \"collection-type\" : { \"type\" : \"string\" }, \"content-type-format\" : { \"type\" : \"string\", \"enum\" : [ \"native\", \"json\" ] }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"disable-features\" : { \"type\" : \"string\" }, \"enable-features\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"include\" : { \"type\" : \"string\" }, \"instance-class\" : { \"type\" : \"string\" }, \"json-view\" : { \"type\" : \"string\" }, \"library\" : { \"type\" : \"string\", \"enum\" : [ \"GoogleProtobuf\", \"Jackson\" ] }, \"module-class-names\" : { \"type\" : \"string\" }, \"module-refs\" : { \"type\" : \"string\" }, \"object-mapper\" : { \"type\" : \"string\" }, \"schema-resolver\" : { \"type\" : \"string\" }, \"timezone\" : { \"type\" : \"string\" }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-default-object-mapper\" : { \"type\" : \"boolean\" }, \"use-list\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.dataformat.RssDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.SoapDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"context-path\" : { \"type\" : \"string\" }, \"element-name-strategy-ref\" : { \"type\" : \"string\" }, \"encoding\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"namespace-prefix-ref\" : { \"type\" : \"string\" }, \"schema\" : { \"type\" : \"string\" }, \"version\" : { \"type\" : \"string\", \"enum\" : [ \"1.1\", \"1.2\" ] } } } ], \"required\" : [ \"context-path\" ] }, \"org.apache.camel.model.dataformat.SwiftMtDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"write-in-json\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.dataformat.SwiftMxDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"read-config-ref\" : { \"type\" : \"string\" }, \"read-message-id\" : { \"type\" : \"string\" }, \"write-config-ref\" : { \"type\" : \"string\" }, \"write-in-json\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.SyslogDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.TarFileDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-empty-directory\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"max-decompressed-size\" : { \"type\" : \"number\" }, \"preserve-path-elements\" : { \"type\" : \"boolean\" }, \"using-iterator\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.ThriftDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"content-type-format\" : { \"type\" : \"string\", \"enum\" : [ \"binary\", \"json\", \"sjson\" ] }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"instance-class\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.dataformat.TidyMarkupDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"data-object-type\" : { \"type\" : \"string\", \"enum\" : [ \"org.w3c.dom.Node\", \"java.lang.String\" ] }, \"id\" : { \"type\" : \"string\" }, \"omit-xml-declaration\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.UniVocityCsvDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"as-map\" : { \"type\" : \"boolean\" }, \"comment\" : { \"type\" : \"string\" }, \"delimiter\" : { \"type\" : \"string\" }, \"empty-value\" : { \"type\" : \"string\" }, \"header-extraction-enabled\" : { \"type\" : \"boolean\" }, \"headers-disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-leading-whitespaces\" : { \"type\" : \"boolean\" }, \"ignore-trailing-whitespaces\" : { \"type\" : \"boolean\" }, \"lazy-load\" : { \"type\" : \"boolean\" }, \"line-separator\" : { \"type\" : \"string\" }, \"normalized-line-separator\" : { \"type\" : \"string\" }, \"null-value\" : { \"type\" : \"string\" }, \"number-of-records-to-read\" : { \"type\" : \"number\" }, \"quote\" : { \"type\" : \"string\" }, \"quote-all-fields\" : { \"type\" : \"boolean\" }, \"quote-escape\" : { \"type\" : \"string\" }, \"skip-empty-lines\" : { \"type\" : \"boolean\" }, \"univocity-header\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityHeader\" } } } }, \"org.apache.camel.model.dataformat.UniVocityFixedDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"as-map\" : { \"type\" : \"boolean\" }, \"comment\" : { \"type\" : \"string\" }, \"empty-value\" : { \"type\" : \"string\" }, \"header-extraction-enabled\" : { \"type\" : \"boolean\" }, \"headers-disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-leading-whitespaces\" : { \"type\" : \"boolean\" }, \"ignore-trailing-whitespaces\" : { \"type\" : \"boolean\" }, \"lazy-load\" : { \"type\" : \"boolean\" }, \"line-separator\" : { \"type\" : \"string\" }, \"normalized-line-separator\" : { \"type\" : \"string\" }, \"null-value\" : { \"type\" : \"string\" }, \"number-of-records-to-read\" : { \"type\" : \"number\" }, \"padding\" : { \"type\" : \"string\" }, \"record-ends-on-newline\" : { \"type\" : \"boolean\" }, \"skip-empty-lines\" : { \"type\" : \"boolean\" }, \"skip-trailing-chars-until-newline\" : { \"type\" : \"boolean\" }, \"univocity-header\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityHeader\" } } } }, \"org.apache.camel.model.dataformat.UniVocityHeader\" : { \"type\" : \"object\", \"properties\" : { \"length\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.UniVocityTsvDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"as-map\" : { \"type\" : \"boolean\" }, \"comment\" : { \"type\" : \"string\" }, \"empty-value\" : { \"type\" : \"string\" }, \"escape-char\" : { \"type\" : \"string\" }, \"header-extraction-enabled\" : { \"type\" : \"boolean\" }, \"headers-disabled\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"ignore-leading-whitespaces\" : { \"type\" : \"boolean\" }, \"ignore-trailing-whitespaces\" : { \"type\" : \"boolean\" }, \"lazy-load\" : { \"type\" : \"boolean\" }, \"line-separator\" : { \"type\" : \"string\" }, \"normalized-line-separator\" : { \"type\" : \"string\" }, \"null-value\" : { \"type\" : \"string\" }, \"number-of-records-to-read\" : { \"type\" : \"number\" }, \"skip-empty-lines\" : { \"type\" : \"boolean\" }, \"univocity-header\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityHeader\" } } } }, \"org.apache.camel.model.dataformat.XMLSecurityDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"add-key-value-for-encrypted-key\" : { \"type\" : \"boolean\" }, \"digest-algorithm\" : { \"type\" : \"string\", \"enum\" : [ \"SHA1\", \"SHA256\", \"SHA512\" ] }, \"id\" : { \"type\" : \"string\" }, \"key-cipher-algorithm\" : { \"type\" : \"string\", \"enum\" : [ \"RSA_v1dot5\", \"RSA_OAEP\", \"RSA_OAEP_11\" ] }, \"key-or-trust-store-parameters-ref\" : { \"type\" : \"string\" }, \"key-password\" : { \"type\" : \"string\" }, \"mgf-algorithm\" : { \"type\" : \"string\", \"enum\" : [ \"MGF1_SHA1\", \"MGF1_SHA256\", \"MGF1_SHA512\" ] }, \"pass-phrase\" : { \"type\" : \"string\" }, \"pass-phrase-byte\" : { \"type\" : \"string\" }, \"recipient-key-alias\" : { \"type\" : \"string\" }, \"secure-tag\" : { \"type\" : \"string\" }, \"secure-tag-contents\" : { \"type\" : \"boolean\" }, \"xml-cipher-algorithm\" : { \"type\" : \"string\", \"enum\" : [ \"TRIPLEDES\", \"AES_128\", \"AES_128_GCM\", \"AES_192\", \"AES_192_GCM\", \"AES_256\", \"AES_256_GCM\", \"SEED_128\", \"CAMELLIA_128\", \"CAMELLIA_192\", \"CAMELLIA_256\" ] } } }, \"org.apache.camel.model.dataformat.XStreamDataFormat\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"aliases\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"content-type-header\" : { \"type\" : \"boolean\" }, \"converters\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"driver\" : { \"type\" : \"string\" }, \"driver-ref\" : { \"type\" : \"string\" }, \"encoding\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"implicit-collections\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"mode\" : { \"type\" : \"string\", \"enum\" : [ \"NO_REFERENCES\", \"ID_REFERENCES\", \"XPATH_RELATIVE_REFERENCES\", \"XPATH_ABSOLUTE_REFERENCES\", \"SINGLE_NODE_XPATH_RELATIVE_REFERENCES\", \"SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES\" ] }, \"omit-fields\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"permissions\" : { \"type\" : \"string\" } } } ] }, \"org.apache.camel.model.dataformat.YAMLDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-any-type\" : { \"type\" : \"boolean\" }, \"allow-recursive-keys\" : { \"type\" : \"boolean\" }, \"constructor\" : { \"type\" : \"string\" }, \"dumper-options\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"library\" : { \"type\" : \"string\", \"enum\" : [ \"SnakeYAML\" ] }, \"max-aliases-for-collections\" : { \"type\" : \"number\" }, \"pretty-flow\" : { \"type\" : \"boolean\" }, \"representer\" : { \"type\" : \"string\" }, \"resolver\" : { \"type\" : \"string\" }, \"type-filter\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.YAMLTypeFilterDefinition\" } }, \"unmarshal-type\" : { \"type\" : \"string\" }, \"use-application-context-class-loader\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.dataformat.YAMLTypeFilterDefinition\" : { \"type\" : \"object\", \"properties\" : { \"type\" : { \"type\" : \"string\" }, \"value\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.ZipDeflaterDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"compression-level\" : { \"type\" : \"string\", \"enum\" : [ \"-1\", \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" ] }, \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.dataformat.ZipFileDataFormat\" : { \"type\" : \"object\", \"properties\" : { \"allow-empty-directory\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"max-decompressed-size\" : { \"type\" : \"number\" }, \"preserve-path-elements\" : { \"type\" : \"boolean\" }, \"using-iterator\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.errorhandler.DeadLetterChannelDefinition\" : { \"type\" : \"object\", \"properties\" : { \"dead-letter-handle-new-exception\" : { \"type\" : \"boolean\" }, \"dead-letter-uri\" : { \"type\" : \"string\" }, \"executor-service-ref\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"log-name\" : { \"type\" : \"string\" }, \"logger-ref\" : { \"type\" : \"string\" }, \"on-exception-occurred-ref\" : { \"type\" : \"string\" }, \"on-prepare-failure-ref\" : { \"type\" : \"string\" }, \"on-redelivery-ref\" : { \"type\" : \"string\" }, \"redelivery-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RedeliveryPolicyDefinition\" }, \"redelivery-policy-ref\" : { \"type\" : \"string\" }, \"retry-while-ref\" : { \"type\" : \"string\" }, \"use-original-body\" : { \"type\" : \"boolean\" }, \"use-original-message\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"dead-letter-uri\" ] }, \"org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"executor-service-ref\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"log-name\" : { \"type\" : \"string\" }, \"logger-ref\" : { \"type\" : \"string\" }, \"on-exception-occurred-ref\" : { \"type\" : \"string\" }, \"on-prepare-failure-ref\" : { \"type\" : \"string\" }, \"on-redelivery-ref\" : { \"type\" : \"string\" }, \"redelivery-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RedeliveryPolicyDefinition\" }, \"redelivery-policy-ref\" : { \"type\" : \"string\" }, \"retry-while-ref\" : { \"type\" : \"string\" }, \"use-original-body\" : { \"type\" : \"boolean\" }, \"use-original-message\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"executor-service-ref\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"log-name\" : { \"type\" : \"string\" }, \"logger-ref\" : { \"type\" : \"string\" }, \"on-exception-occurred-ref\" : { \"type\" : \"string\" }, \"on-prepare-failure-ref\" : { \"type\" : \"string\" }, \"on-redelivery-ref\" : { \"type\" : \"string\" }, \"redelivery-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RedeliveryPolicyDefinition\" }, \"redelivery-policy-ref\" : { \"type\" : \"string\" }, \"retry-while-ref\" : { \"type\" : \"string\" }, \"rollback-logging-level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"transacted-policy-ref\" : { \"type\" : \"string\" }, \"use-original-body\" : { \"type\" : \"boolean\" }, \"use-original-message\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.errorhandler.NoErrorHandlerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.errorhandler.RefErrorHandlerDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.errorhandler.SpringTransactionErrorHandlerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"executor-service-ref\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"log-name\" : { \"type\" : \"string\" }, \"logger-ref\" : { \"type\" : \"string\" }, \"on-exception-occurred-ref\" : { \"type\" : \"string\" }, \"on-prepare-failure-ref\" : { \"type\" : \"string\" }, \"on-redelivery-ref\" : { \"type\" : \"string\" }, \"redelivery-policy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RedeliveryPolicyDefinition\" }, \"redelivery-policy-ref\" : { \"type\" : \"string\" }, \"retry-while-ref\" : { \"type\" : \"string\" }, \"rollback-logging-level\" : { \"type\" : \"string\", \"enum\" : [ \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"OFF\" ] }, \"transacted-policy-ref\" : { \"type\" : \"string\" }, \"use-original-body\" : { \"type\" : \"boolean\" }, \"use-original-message\" : { \"type\" : \"boolean\" } } }, \"org.apache.camel.model.language.CSimpleExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.ConstantExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.DatasonnetExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"body-media-type\" : { \"type\" : \"string\" }, \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"output-media-type\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.ExchangePropertyExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.ExpressionDefinition\" : { \"type\" : \"object\", \"properties\" : { \"constant\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ConstantExpression\" }, \"csimple\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.CSimpleExpression\" }, \"datasonnet\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.DatasonnetExpression\" }, \"exchange-property\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExchangePropertyExpression\" }, \"exchangeProperty\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExchangePropertyExpression\" }, \"groovy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.GroovyExpression\" }, \"header\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.HeaderExpression\" }, \"hl7terser\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.Hl7TerserExpression\" }, \"joor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JoorExpression\" }, \"jq\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JqExpression\" }, \"js\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JavaScriptExpression\" }, \"jsonpath\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.JsonPathExpression\" }, \"language\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.LanguageExpression\" }, \"method\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.MethodCallExpression\" }, \"mvel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.MvelExpression\" }, \"ognl\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.OgnlExpression\" }, \"python\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.PythonExpression\" }, \"ref\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.RefExpression\" }, \"simple\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.SimpleExpression\" }, \"spel\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.SpELExpression\" }, \"tokenize\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.TokenizerExpression\" }, \"xpath\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XPathExpression\" }, \"xquery\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XQueryExpression\" }, \"xtokenize\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.XMLTokenizerExpression\" } } }, \"org.apache.camel.model.language.GroovyExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.HeaderExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.Hl7TerserExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"property-name\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.JavaScriptExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.JoorExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"pre-compile\" : { \"type\" : \"boolean\" }, \"result-type\" : { \"type\" : \"string\" }, \"single-quotes\" : { \"type\" : \"boolean\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.JqExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"property-name\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.JsonPathExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"allow-easy-predicate\" : { \"type\" : \"boolean\" }, \"allow-simple\" : { \"type\" : \"boolean\" }, \"expression\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"option\" : { \"type\" : \"string\", \"enum\" : [ \"DEFAULT_PATH_LEAF_TO_NULL\", \"ALWAYS_RETURN_LIST\", \"AS_PATH_LIST\", \"SUPPRESS_EXCEPTIONS\", \"REQUIRE_PROPERTIES\" ] }, \"property-name\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"suppress-exceptions\" : { \"type\" : \"boolean\" }, \"trim\" : { \"type\" : \"boolean\" }, \"unpack-array\" : { \"type\" : \"boolean\" }, \"write-as-string\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.LanguageExpression\" : { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"language\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"expression\", \"language\" ] }, \"org.apache.camel.model.language.MethodCallExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"bean-type\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"method\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"scope\" : { \"type\" : \"string\", \"enum\" : [ \"Singleton\", \"Request\", \"Prototype\" ] }, \"trim\" : { \"type\" : \"boolean\" } } } ] }, \"org.apache.camel.model.language.MvelExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.OgnlExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.PythonExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.RefExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.SimpleExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.SpELExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.TokenizerExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"end-token\" : { \"type\" : \"string\" }, \"group\" : { \"type\" : \"string\" }, \"group-delimiter\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"include-tokens\" : { \"type\" : \"boolean\" }, \"inherit-namespace-tag-name\" : { \"type\" : \"string\" }, \"property-name\" : { \"type\" : \"string\" }, \"regex\" : { \"type\" : \"boolean\" }, \"skip-first\" : { \"type\" : \"boolean\" }, \"token\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" }, \"xml\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"token\" ] }, \"org.apache.camel.model.language.XMLTokenizerExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"type\" : \"string\" }, \"group\" : { \"type\" : \"number\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"mode\" : { \"type\" : \"string\", \"enum\" : [ \"i\", \"w\", \"u\", \"t\" ] }, \"namespace\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"property-name\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.XPathExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"document-type\" : { \"type\" : \"string\" }, \"expression\" : { \"type\" : \"string\" }, \"factory-ref\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"log-namespaces\" : { \"type\" : \"boolean\" }, \"namespace\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"object-model\" : { \"type\" : \"string\" }, \"pre-compile\" : { \"type\" : \"boolean\" }, \"property-name\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\", \"enum\" : [ \"NUMBER\", \"STRING\", \"BOOLEAN\", \"NODESET\", \"NODE\" ] }, \"saxon\" : { \"type\" : \"boolean\" }, \"thread-safety\" : { \"type\" : \"boolean\" }, \"trim\" : { \"type\" : \"boolean\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.language.XQueryExpression\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"configuration-ref\" : { \"type\" : \"string\" }, \"expression\" : { \"type\" : \"string\" }, \"header-name\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"namespace\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.PropertyDefinition\" } }, \"property-name\" : { \"type\" : \"string\" }, \"result-type\" : { \"type\" : \"string\" }, \"trim\" : { \"type\" : \"boolean\" }, \"type\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"expression\" ] }, \"org.apache.camel.model.loadbalancer.CustomLoadBalancerDefinition\" : { \"oneOf\" : [ { \"type\" : \"string\" }, { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" } } } ], \"required\" : [ \"ref\" ] }, \"org.apache.camel.model.loadbalancer.FailoverLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"exception\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"id\" : { \"type\" : \"string\" }, \"maximum-failover-attempts\" : { \"type\" : \"string\" }, \"round-robin\" : { \"type\" : \"string\" }, \"sticky\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.loadbalancer.RandomLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.loadbalancer.StickyLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"correlation-expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition\" }, \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.loadbalancer.TopicLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"id\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.loadbalancer.WeightedLoadBalancerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"distribution-ratio\" : { \"type\" : \"string\" }, \"distribution-ratio-delimiter\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"round-robin\" : { \"type\" : \"boolean\" } }, \"required\" : [ \"distribution-ratio\" ] }, \"org.apache.camel.model.rest.ApiKeyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"in-cookie\" : { \"type\" : \"boolean\" }, \"in-header\" : { \"type\" : \"boolean\" }, \"in-query\" : { \"type\" : \"boolean\" }, \"key\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\", \"name\" ] }, \"org.apache.camel.model.rest.BasicAuthDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"key\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.rest.BearerTokenDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"format\" : { \"type\" : \"string\" }, \"key\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.rest.DeleteDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.GetDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.HeadDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.MutualTLSDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"key\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.rest.OAuth2Definition\" : { \"type\" : \"object\", \"properties\" : { \"authorization-url\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"flow\" : { \"type\" : \"string\", \"enum\" : [ \"implicit\", \"password\", \"application\", \"clientCredentials\", \"accessCode\", \"authorizationCode\" ] }, \"key\" : { \"type\" : \"string\" }, \"refresh-url\" : { \"type\" : \"string\" }, \"scopes\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"token-url\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.rest.OpenIdConnectDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"key\" : { \"type\" : \"string\" }, \"url\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\", \"url\" ] }, \"org.apache.camel.model.rest.ParamDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allowable-values\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ValueDefinition\" } }, \"array-type\" : { \"type\" : \"string\" }, \"collection-format\" : { \"type\" : \"string\", \"enum\" : [ \"csv\", \"multi\", \"pipes\", \"ssv\", \"tsv\" ] }, \"data-format\" : { \"type\" : \"string\" }, \"data-type\" : { \"type\" : \"string\" }, \"default-value\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"examples\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"name\" : { \"type\" : \"string\" }, \"required\" : { \"type\" : \"boolean\" }, \"type\" : { \"type\" : \"string\", \"enum\" : [ \"body\", \"formData\", \"header\", \"path\", \"query\" ] } }, \"required\" : [ \"name\", \"type\" ] }, \"org.apache.camel.model.rest.PatchDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.PostDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.PutDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"deprecated\" : { \"type\" : \"boolean\" }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"param\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ParamDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"response-message\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseMessageDefinition\" } }, \"route-id\" : { \"type\" : \"string\" }, \"security\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"to\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ToDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.ResponseHeaderDefinition\" : { \"type\" : \"object\", \"properties\" : { \"allowable-values\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.ValueDefinition\" } }, \"array-type\" : { \"type\" : \"string\" }, \"collection-format\" : { \"type\" : \"string\", \"enum\" : [ \"csv\", \"multi\", \"pipes\", \"ssv\", \"tsv\" ] }, \"data-format\" : { \"type\" : \"string\" }, \"data-type\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"example\" : { \"type\" : \"string\" }, \"name\" : { \"type\" : \"string\" } }, \"required\" : [ \"name\" ] }, \"org.apache.camel.model.rest.ResponseMessageDefinition\" : { \"type\" : \"object\", \"properties\" : { \"code\" : { \"type\" : \"string\" }, \"examples\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"header\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ResponseHeaderDefinition\" } }, \"message\" : { \"type\" : \"string\" }, \"response-model\" : { \"type\" : \"string\" } }, \"required\" : [ \"message\" ] }, \"org.apache.camel.model.rest.RestBindingDefinition\" : { \"type\" : \"object\", \"properties\" : { \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"component\" : { \"type\" : \"string\" }, \"consumes\" : { \"type\" : \"string\" }, \"description\" : { \"type\" : \"string\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"id\" : { \"type\" : \"string\" }, \"out-type\" : { \"type\" : \"string\" }, \"produces\" : { \"type\" : \"string\" }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.RestConfigurationDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-component\" : { \"type\" : \"string\", \"enum\" : [ \"openapi\", \"swagger\" ] }, \"api-context-path\" : { \"type\" : \"string\" }, \"api-context-route-id\" : { \"type\" : \"string\" }, \"api-host\" : { \"type\" : \"string\" }, \"api-property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"api-vendor-extension\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"auto\", \"json\", \"json_xml\", \"off\", \"xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"component\" : { \"type\" : \"string\", \"enum\" : [ \"platform-http\", \"servlet\", \"jetty\", \"undertow\", \"netty-http\", \"coap\" ] }, \"component-property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"consumer-property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"context-path\" : { \"type\" : \"string\" }, \"cors-headers\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"data-format-property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"endpoint-property\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestPropertyDefinition\" } }, \"host\" : { \"type\" : \"string\" }, \"host-name-resolver\" : { \"type\" : \"string\", \"enum\" : [ \"allLocalIp\", \"localHostName\", \"localIp\" ] }, \"inline-routes\" : { \"type\" : \"boolean\" }, \"json-data-format\" : { \"type\" : \"string\" }, \"port\" : { \"type\" : \"string\" }, \"producer-api-doc\" : { \"type\" : \"string\" }, \"producer-component\" : { \"type\" : \"string\", \"enum\" : [ \"vertx-http\", \"http\", \"undertow\", \"netty-http\" ] }, \"scheme\" : { \"type\" : \"string\" }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"use-x-forward-headers\" : { \"type\" : \"boolean\" }, \"xml-data-format\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.RestDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-docs\" : { \"type\" : \"boolean\" }, \"binding-mode\" : { \"type\" : \"string\", \"enum\" : [ \"off\", \"auto\", \"json\", \"xml\", \"json_xml\" ] }, \"client-request-validation\" : { \"type\" : \"boolean\" }, \"consumes\" : { \"type\" : \"string\" }, \"delete\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.DeleteDefinition\" } }, \"description\" : { \"type\" : \"string\" }, \"disabled\" : { \"type\" : \"boolean\" }, \"enable-cors\" : { \"type\" : \"boolean\" }, \"get\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.GetDefinition\" } }, \"head\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.HeadDefinition\" } }, \"id\" : { \"type\" : \"string\" }, \"patch\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.PatchDefinition\" } }, \"path\" : { \"type\" : \"string\" }, \"post\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.PostDefinition\" } }, \"produces\" : { \"type\" : \"string\" }, \"put\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.PutDefinition\" } }, \"security-definitions\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestSecuritiesDefinition\" }, \"security-requirements\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition\" } }, \"skip-binding-on-error-code\" : { \"type\" : \"boolean\" }, \"tag\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.rest.RestPropertyDefinition\" : { \"type\" : \"object\", \"properties\" : { \"key\" : { \"type\" : \"string\" }, \"value\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\", \"value\" ] }, \"org.apache.camel.model.rest.RestSecuritiesDefinition\" : { \"type\" : \"object\", \"properties\" : { \"api-key\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.ApiKeyDefinition\" }, \"basic-auth\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.BasicAuthDefinition\" }, \"bearer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.BearerTokenDefinition\" }, \"mutual-tls\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.MutualTLSDefinition\" }, \"oauth2\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.OAuth2Definition\" }, \"open-id-connect\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.OpenIdConnectDefinition\" } } }, \"org.apache.camel.model.rest.RestsDefinition\" : { \"type\" : \"object\", \"properties\" : { \"description\" : { \"type\" : \"string\" }, \"id\" : { \"type\" : \"string\" }, \"rest\" : { \"type\" : \"array\", \"items\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestDefinition\" } } } }, \"org.apache.camel.model.rest.SecurityDefinition\" : { \"type\" : \"object\", \"properties\" : { \"key\" : { \"type\" : \"string\" }, \"scopes\" : { \"type\" : \"string\" } }, \"required\" : [ \"key\" ] }, \"org.apache.camel.model.transformer.CustomTransformerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"class-name\" : { \"type\" : \"string\" }, \"from-type\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" }, \"scheme\" : { \"type\" : \"string\" }, \"to-type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.transformer.DataFormatTransformerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"any23\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Any23DataFormat\" }, \"asn1\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ASN1DataFormat\" }, \"avro\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.AvroDataFormat\" }, \"barcode\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BarcodeDataFormat\" }, \"base64\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat\" }, \"bindy\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.BindyDataFormat\" }, \"cbor\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CBORDataFormat\" }, \"crypto\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CryptoDataFormat\" }, \"csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CsvDataFormat\" }, \"custom\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.CustomDataFormat\" }, \"fhir-json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirJsonDataFormat\" }, \"fhir-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FhirXmlDataFormat\" }, \"flatpack\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.FlatpackDataFormat\" }, \"from-type\" : { \"type\" : \"string\" }, \"grok\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GrokDataFormat\" }, \"gzip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.GzipDeflaterDataFormat\" }, \"hl7\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.HL7DataFormat\" }, \"ical\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.IcalDataFormat\" }, \"jackson-xml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JacksonXMLDataFormat\" }, \"jaxb\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JaxbDataFormat\" }, \"json\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonDataFormat\" }, \"json-api\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.JsonApiDataFormat\" }, \"lzf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.LZFDataFormat\" }, \"mime-multipart\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.MimeMultipartDataFormat\" }, \"pgp\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.PGPDataFormat\" }, \"protobuf\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ProtobufDataFormat\" }, \"rss\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.RssDataFormat\" }, \"scheme\" : { \"type\" : \"string\" }, \"soap\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SoapDataFormat\" }, \"swift-mt\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMtDataFormat\" }, \"swift-mx\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SwiftMxDataFormat\" }, \"syslog\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.SyslogDataFormat\" }, \"tar-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TarFileDataFormat\" }, \"thrift\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ThriftDataFormat\" }, \"tidy-markup\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.TidyMarkupDataFormat\" }, \"to-type\" : { \"type\" : \"string\" }, \"univocity-csv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityCsvDataFormat\" }, \"univocity-fixed\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityFixedDataFormat\" }, \"univocity-tsv\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.UniVocityTsvDataFormat\" }, \"xml-security\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XMLSecurityDataFormat\" }, \"xstream\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.XStreamDataFormat\" }, \"yaml\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.YAMLDataFormat\" }, \"zip-deflater\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipDeflaterDataFormat\" }, \"zip-file\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.dataformat.ZipFileDataFormat\" } } }, \"org.apache.camel.model.transformer.EndpointTransformerDefinition\" : { \"type\" : \"object\", \"properties\" : { \"from-type\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" }, \"scheme\" : { \"type\" : \"string\" }, \"to-type\" : { \"type\" : \"string\" }, \"uri\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.transformer.TransformersDefinition\" : { \"type\" : \"object\", \"properties\" : { \"custom-transformer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.transformer.CustomTransformerDefinition\" }, \"data-format-transformer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.transformer.DataFormatTransformerDefinition\" }, \"endpoint-transformer\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.transformer.EndpointTransformerDefinition\" } } }, \"org.apache.camel.model.validator.CustomValidatorDefinition\" : { \"type\" : \"object\", \"properties\" : { \"class-name\" : { \"type\" : \"string\" }, \"ref\" : { \"type\" : \"string\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.validator.EndpointValidatorDefinition\" : { \"type\" : \"object\", \"properties\" : { \"ref\" : { \"type\" : \"string\" }, \"type\" : { \"type\" : \"string\" }, \"uri\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.validator.PredicateValidatorDefinition\" : { \"type\" : \"object\", \"properties\" : { \"expression\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition\" }, \"type\" : { \"type\" : \"string\" } } }, \"org.apache.camel.model.validator.ValidatorsDefinition\" : { \"type\" : \"object\", \"properties\" : { \"custom-validator\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.validator.CustomValidatorDefinition\" }, \"endpoint-validator\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.validator.EndpointValidatorDefinition\" }, \"predicate-validator\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.validator.PredicateValidatorDefinition\" } } } }, \"properties\" : { \"beans\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.BeansDeserializer\" }, \"error-handler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.ErrorHandlerBuilderDeserializer\" }, \"errorHandler\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.ErrorHandlerBuilderDeserializer\" }, \"from\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.dsl.yaml.deserializers.RouteFromDefinitionDeserializer\" }, \"on-exception\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnExceptionDefinition\" }, \"onException\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.OnExceptionDefinition\" }, \"route-configuration\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition\" }, \"routeConfiguration\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition\" }, \"route\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteDefinition\" }, \"route-template\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteTemplateDefinition\" }, \"routeTemplate\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.RouteTemplateDefinition\" }, \"templated-route\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition\" }, \"templatedRoute\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition\" }, \"rest\" : { \"$ref\" : \"#/items/definitions/org.apache.camel.model.rest.RestDefinition\" } } } }" diff --git a/workflowproj/go.mod b/workflowproj/go.mod deleted file mode 100644 index 370528a6..00000000 --- a/workflowproj/go.mod +++ /dev/null @@ -1,87 +0,0 @@ -module github.com/kubesmarts/logic-operator/workflowproj - -go 1.26.0 - -// Internal dependencies -replace github.com/kubesmarts/logic-operator/api => ../api - -require ( - github.com/kubesmarts/logic-operator/api v0.0.0 - github.com/magiconair/properties v1.8.7 - github.com/pb33f/libopenapi v0.8.4 - github.com/pkg/errors v0.9.1 - github.com/santhosh-tekuri/jsonschema/v5 v5.3.0 - github.com/serverlessworkflow/sdk-go/v2 v2.5.0 - github.com/stretchr/testify v1.9.0 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/client-go v0.31.1 - sigs.k8s.io/controller-runtime v0.19.0 - sigs.k8s.io/yaml v1.4.0 -) - -require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/relvacode/iso8601 v1.4.0 // indirect - github.com/sosodev/duration v1.3.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect - github.com/x448/float16 v0.8.4 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/time v0.5.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect -) diff --git a/workflowproj/go.sum b/workflowproj/go.sum deleted file mode 100644 index 4ad0a991..00000000 --- a/workflowproj/go.sum +++ /dev/null @@ -1,313 +0,0 @@ -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/pb33f/libopenapi v0.8.4 h1:hP6etldkapogvEfILaCVrBNh9DwzK/ZKGrNPm3qAIwU= -github.com/pb33f/libopenapi v0.8.4/go.mod h1:lvUmCtjgHUGVj6WzN3I5/CS9wkXtyN3Ykjh6ZZP5lrI= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXUJs= -github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.0 h1:uIkTLo0AGRc8l7h5l9r+GcYi9qfVPt6lD4/bhmzfiKo= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0 h1:bvD461rbaj0PcRjRwsBt7tqHie2M10otryB+BjzHg5Q= -github.com/serverlessworkflow/sdk-go/v2 v2.5.0/go.mod h1:kuvTQCTAb9vzDaeJ1JPY+sBGiHr9OX1g/Rxuk82c8mI= -github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= -github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= -github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= -knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c/go.mod h1:HHRXEd7ZlFpthgE+rwAZ6MUVnuJOAeolnaFSthXloUQ= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/workflowproj/io.go b/workflowproj/io.go deleted file mode 100644 index 152d37be..00000000 --- a/workflowproj/io.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "fmt" - "os" - "path/filepath" - "reflect" - "strings" - - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/yaml" -) - -const ( - yamlFileExt = ".yaml" -) - -func ensurePath(path string) error { - err := os.MkdirAll(path, os.ModePerm) - if err != nil { - return err - } - return nil -} - -func saveAsKubernetesManifest(object client.Object, savePath string, prefix int) error { - if reflect.ValueOf(object).IsNil() { - return nil - } - filename := strings.ToLower(fmt.Sprintf("%02d-%s_%s%s", - prefix, - object.GetObjectKind().GroupVersionKind().Kind, - object.GetName(), - yamlFileExt)) - finalPath := filepath.Join(savePath, filename) - contents, err := yaml.Marshal(object) - if err != nil { - return err - } - err = os.WriteFile(finalPath, contents, os.ModePerm) - if err != nil { - return err - } - return nil -} diff --git a/workflowproj/operator.go b/workflowproj/operator.go deleted file mode 100644 index ee3961f9..00000000 --- a/workflowproj/operator.go +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "fmt" - - "github.com/kubesmarts/logic-operator/api/version" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -const ( - workflowUserConfigMapNameSuffix = "-props" - workflowUserSecretConfigMapNameSuffix = "-secrets" - // ApplicationPropertiesFileName is the default application properties file name holding user properties - ApplicationPropertiesFileName = "application.properties" - // SecretPropertiesFileName is the default application secret properties file name holding user secret properties - SecretPropertiesFileName = "secret.properties" - workflowManagedConfigMapNameSuffix = "-managed-props" - // LabelApp key to use among object selectors, "app" is used among k8s applications to group objects in some UI consoles - LabelApp = "app" - // LabelAppNamespace namespace the k8s application is deployed - LabelAppNamespace = "app-namespace" - // LabelService key to use among object selectors - LabelService = metadata.Domain + "/service" - // LabelWorkflow specialized label managed by the controller - LabelWorkflow = metadata.Domain + "/workflow-app" - // LabelWorkflowNamespace specialized label managed by the controller indicating the namespace of the workflow - LabelWorkflowNamespace = metadata.Domain + "/workflow-namespace" -) - -// SetTypeToObject sets the Kind and ApiVersion to a given object since the default constructor won't do it. -// See: https://github.com/kubernetes/client-go/issues/308#issuecomment-700099260 -func SetTypeToObject(obj runtime.Object, s *runtime.Scheme) error { - gvks, _, err := s.ObjectKinds(obj) - if err != nil { - return err - } - for _, gvk := range gvks { - if len(gvk.Kind) == 0 { - continue - } - if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { - continue - } - obj.GetObjectKind().SetGroupVersionKind(gvk) - break - } - return nil -} - -// GetWorkflowUserPropertiesConfigMapName gets the default ConfigMap name that holds the user application property for the given workflow -func GetWorkflowUserPropertiesConfigMapName(workflow *operatorapi.SonataFlow) string { - return workflow.Name + workflowUserConfigMapNameSuffix -} - -// GetWorkflowManagedPropertiesConfigMapName gets the default ConfigMap name that holds the managed application property for the given workflow -func GetWorkflowManagedPropertiesConfigMapName(workflow *operatorapi.SonataFlow) string { - return workflow.Name + workflowManagedConfigMapNameSuffix -} - -// GetManagedPropertiesFileName gets the default ConfigMap name that holds the managed application property for the given workflow -func GetManagedPropertiesFileName(workflow *operatorapi.SonataFlow) string { - profile := metadata.QuarkusProdProfile - if IsDevProfile(workflow) { - profile = metadata.QuarkusDevProfile - } - return fmt.Sprintf("application-%s.properties", profile) -} - -// GetWorkflowUserSecretPropertiesConfigMapName gets the default ConfigMap name that holds the user application secrets property for the given workflow -func GetWorkflowUserSecretPropertiesConfigMapName(workflow *operatorapi.SonataFlow) string { - return workflow.Name + workflowUserSecretConfigMapNameSuffix -} - -// GetDefaultLabels gets the default labels based on the given workflow. -func GetDefaultLabels(workflow *operatorapi.SonataFlow) map[string]string { - labels := map[string]string{ - LabelWorkflow: workflow.Name, - metadata.KubernetesLabelName: workflow.Name, - metadata.KubernetesLabelInstance: workflow.Name, - metadata.KubernetesLabelComponent: "serverless-workflow", - metadata.KubernetesLabelManagedBy: "sonataflow-operator", - metadata.KubernetesLabelVersion: version.GetImageTagVersion(), - LabelApp: workflow.Name, - LabelWorkflowNamespace: workflow.Namespace, - } - if workflow.Status.Platform != nil { - labels[metadata.KubernetesLabelPartOf] = workflow.Status.Platform.Name - } - return labels - -} -func GetSelectorLabels(workflow *operatorapi.SonataFlow) map[string]string { - labels := GetDefaultLabels(workflow) - delete(labels, metadata.KubernetesLabelPartOf) - return labels -} - -// SetMergedLabels adds the merged labels to the given object. -func SetMergedLabels(workflow *operatorapi.SonataFlow, object metav1.Object) { - object.SetLabels(GetMergedLabels(workflow)) -} - -// GetMergedLabels gets labels based on the given workflow, includes their own labels, merged with the default ones. -func GetMergedLabels(workflow *operatorapi.SonataFlow) map[string]string { - mergedLabels := make(map[string]string) - if labels := workflow.GetLabels(); labels != nil { - for k, v := range labels { - mergedLabels[k] = v - } - } - for k, v := range GetDefaultLabels(workflow) { - mergedLabels[k] = v - } - return mergedLabels -} - -// CreateNewUserPropsConfigMap creates a new empty ConfigMap object to hold the user application properties of the workflow. -func CreateNewUserPropsConfigMap(workflow *operatorapi.SonataFlow) *corev1.ConfigMap { - return &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: GetWorkflowUserPropertiesConfigMapName(workflow), - Namespace: workflow.Namespace, - Labels: GetMergedLabels(workflow), - }, - Data: map[string]string{ApplicationPropertiesFileName: ""}, - } -} - -func CreateNewSecretPropsConfigMap(workflow *operatorapi.SonataFlow) *corev1.Secret { - return &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: GetWorkflowUserSecretPropertiesConfigMapName(workflow), - Namespace: workflow.Namespace, - Labels: GetMergedLabels(workflow), - }, - } - -} - -// CreateNewManagedPropsConfigMap creates a new ConfigMap object to hold the managed application properties of the workflows. -func CreateNewManagedPropsConfigMap(workflow *operatorapi.SonataFlow, properties string) *corev1.ConfigMap { - return &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: GetWorkflowManagedPropertiesConfigMapName(workflow), - Namespace: workflow.Namespace, - Labels: GetMergedLabels(workflow), - }, - Data: map[string]string{GetManagedPropertiesFileName(workflow): properties}, - } -} - -// SetWorkflowProfile adds the profile annotation to the workflow -func SetWorkflowProfile(workflow *operatorapi.SonataFlow, profile metadata.ProfileType) { - if workflow.Annotations == nil { - workflow.Annotations = map[string]string{} - } - workflow.Annotations[metadata.Profile] = string(profile) -} diff --git a/workflowproj/operator_test.go b/workflowproj/operator_test.go deleted file mode 100644 index 90fee192..00000000 --- a/workflowproj/operator_test.go +++ /dev/null @@ -1,394 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -func TestCreateNewManagedPropsConfigMap(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - properties string - } - tests := []struct { - name string - args args - want map[string]string - }{ - { - "when workflow has labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{ - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "app.kubernetes.io/part-of": "someplatform", - }}}}, - - map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "app.kubernetes.io/part-of": "someplatform", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - { - "when the workflow has no labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{}}}}, - - map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - // if the workflow is missing a platform then the managed properties won't have them - //"app.kubernetes.io/part-of": "someplatform", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, CreateNewManagedPropsConfigMap( - tt.args.workflow, tt.args.properties).GetLabels(), - "CreateNewManagedPropsConfigMap(%v, %v)", tt.args.workflow, tt.args.properties) - }) - } -} - -func TestCreateNewUserPropsConfigMap(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want *corev1.ConfigMap - }{ - { - "when the workflow has no labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{}}}}, - - &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: t.Name() + "-props", - Namespace: "", - Labels: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - Data: map[string]string{ - "application.properties": "", - }, - }, - }, - { - "when the workflow has labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{ - "older-label": t.Name(), - }}}}, - - &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: t.Name() + "-props", - Namespace: "", - Labels: map[string]string{ - "older-label": t.Name(), - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - Data: map[string]string{ - "application.properties": "", - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, CreateNewUserPropsConfigMap(tt.args.workflow), "CreateNewUserPropsConfigMap(%v)", tt.args.workflow) - }) - } -} - -func TestGetDefaultLabels(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want map[string]string - }{ - { - "when the workflow has no labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{}}}}, - - map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - // if the workflow is missing a platform then the managed properties won't have them - //"app.kubernetes.io/part-of": "someplatform", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - { - "when workflow has labels", - args{workflow: &operatorapi.SonataFlow{ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{ - "some-older-label-should-not-be-included": t.Name(), - }}}}, - - map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetDefaultLabels(tt.args.workflow), "GetDefaultLabels(%v)", tt.args.workflow) - }) - } -} - -func TestGetManagedPropertiesFileName(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want string - }{ - { - name: "test", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - }, - }}, - want: "application-prod.properties", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetManagedPropertiesFileName(tt.args.workflow), "GetManagedPropertiesFileName(%v)", tt.args.workflow) - }) - } -} - -func TestGetMergedLabels(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want map[string]string - }{ - { - name: "when workflow has no labels", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - }, - }}, - want: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - { - name: "when workflow has labels", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{ - "some-older-label": t.Name(), - }, - }, - }}, - want: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - "some-older-label": t.Name(), - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetMergedLabels(tt.args.workflow), "GetMergedLabels(%v)", tt.args.workflow) - }) - } -} - -func TestGetSelectorLabels(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want map[string]string - }{ - { - name: "when workflow has no labels", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - }, - }}, - want: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - { - name: "when workflow has labels", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - Labels: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - }}, - want: map[string]string{ - "app": t.Name(), - "app.kubernetes.io/name": t.Name(), - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - "sonataflow.org/workflow-app": t.Name(), - "sonataflow.org/workflow-namespace": "", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetSelectorLabels(tt.args.workflow), "GetSelectorLabels(%v)", tt.args.workflow) - }) - } -} - -func TestGetWorkflowManagedPropertiesConfigMapName(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - var tests = []struct { - name string - args args - want string - }{ - { - name: "managed props configMap name", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - }, - }}, - want: t.Name() + "-managed-props", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetWorkflowManagedPropertiesConfigMapName(tt.args.workflow), "GetWorkflowManagedPropertiesConfigMapName(%v)", tt.args.workflow) - }) - } -} - -func TestGetWorkflowUserPropertiesConfigMapName(t *testing.T) { - type args struct { - workflow *operatorapi.SonataFlow - } - tests := []struct { - name string - args args - want string - }{ - { - name: "test", - args: args{workflow: &operatorapi.SonataFlow{ - ObjectMeta: v1.ObjectMeta{ - Name: t.Name(), - }, - }}, - want: t.Name() + "-props", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, GetWorkflowUserPropertiesConfigMapName(tt.args.workflow), "GetWorkflowUserPropertiesConfigMapName(%v)", tt.args.workflow) - }) - } -} diff --git a/workflowproj/resources.go b/workflowproj/resources.go deleted file mode 100644 index bd96819b..00000000 --- a/workflowproj/resources.go +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "strings" - - "github.com/pb33f/libopenapi" - libopenapiutils "github.com/pb33f/libopenapi/utils" - "github.com/santhosh-tekuri/jsonschema/v5" - "k8s.io/apimachinery/pkg/util/yaml" -) - -type ResourceKind int - -const ( - OpenApiResource ResourceKind = iota - AsyncApiResource - CamelRouteResource - GenericResource -) - -// ParseResourceKind tries to parse the contents of the given resource and find the correct type. -// Async and OpenAPI files are pretty fast to parse (0.00s). -// Camel and generic files can take a fair price from the CPU (0.03s on the i5) since it takes more processing power. -func ParseResourceKind(contents []byte) ResourceKind { - if len(contents) == 0 { - return GenericResource - } - doc, err := libopenapi.NewDocument(contents) - if err == nil { - switch doc.GetSpecInfo().SpecType { - case libopenapiutils.AsyncApi: - return AsyncApiResource - default: - return OpenApiResource - } - } - if err = validateCamelRoute(contents); err == nil { - return CamelRouteResource - } - return GenericResource -} - -func validateCamelRoute(contents []byte) error { - schema, err := jsonschema.CompileString("camel.json", camelSchema) - if err != nil { - return err - } - decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(string(contents)), 512) - var v []interface{} - if err = decoder.Decode(&v); err != nil { - return err - } - return schema.Validate(v) -} diff --git a/workflowproj/resources_test.go b/workflowproj/resources_test.go deleted file mode 100644 index da8dff73..00000000 --- a/workflowproj/resources_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "os" - "testing" -) - -func TestParseResourceType(t *testing.T) { - type args struct { - contents []byte - } - tests := []struct { - name string - args args - want ResourceKind - }{ - {name: "valid openapi", args: args{contents: getResourceContents("valid-openapi.yaml")}, want: OpenApiResource}, - {name: "valid asyncapi", args: args{contents: getResourceContents("valid-asyncapi.yaml")}, want: AsyncApiResource}, - {name: "valid camel", args: args{contents: getResourceContents("valid-camelroute.yaml")}, want: CamelRouteResource}, - {name: "valid openapi (JSON)", args: args{contents: getResourceContents("valid-openapi.json")}, want: OpenApiResource}, - {name: "valid asyncapi (JSON)", args: args{contents: getResourceContents("valid-asyncapi.json")}, want: AsyncApiResource}, - {name: "valid camel (JSON)", args: args{contents: getResourceContents("valid-camelroute.json")}, want: CamelRouteResource}, - {name: "generic resource", args: args{contents: getResourceContents("mygeneric.wsdl")}, want: GenericResource}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := ParseResourceKind(tt.args.contents) - if got != tt.want { - t.Errorf("ParseResourceKind() got = %v, want %v", got, tt.want) - } - }) - } -} - -func getResourceContents(filename string) []byte { - contents, err := os.ReadFile("testdata/" + filename) - if err != nil { - panic(err) - } - return contents -} diff --git a/workflowproj/testdata/mygeneric.wsdl b/workflowproj/testdata/mygeneric.wsdl deleted file mode 100644 index 33dee309..00000000 --- a/workflowproj/testdata/mygeneric.wsdl +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Returns the word corresponding to the positive number passed as parameter. Limited to quadrillions. - - - - - Returns the non-zero dollar amount of the passed number. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The Number Conversion Web Service, implemented with Visual DataFlex, provides functions that convert numbers into words or dollar amounts. - - - - - - - - diff --git a/workflowproj/testdata/valid-asyncapi.json b/workflowproj/testdata/valid-asyncapi.json deleted file mode 100644 index d6b64171..00000000 --- a/workflowproj/testdata/valid-asyncapi.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "asyncapi": "2.0.0", - "id": "urn:com:http:server", - "info": { - "title": "Http Application", - "version": "1.0.0", - "description": "Http Application", - "license": { - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0" - } - }, - "servers": { - "production": { - "url": "localhost:8080", - "description": "Development server", - "protocol": "http" - } - }, - "channels": { - "first": { - "description": "A message channel", - "subscribe": { - "summary": "Get messages", - "message": { - "$ref": "#/components/messages/message" - } - }, - "publish": { - "summary": "Send messages", - "message": { - "$ref": "#/components/messages/message" - }, - "traits": [ - { - "bindings": { - "flogo-kafka": { - "partitions": "0", - "offset": 0 - } - } - } - ] - } - } - }, - "components": { - "messages": { - "message": { - "name": "message", - "summary": "A message", - "contentType": "application/json", - "payload": { - "$ref": "#/components/schemas/message" - } - } - }, - "schemas": { - "message": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "age": { - "type": "integer" - } - } - } - } - } -} diff --git a/workflowproj/testdata/valid-asyncapi.yaml b/workflowproj/testdata/valid-asyncapi.yaml deleted file mode 100644 index 15b50aa5..00000000 --- a/workflowproj/testdata/valid-asyncapi.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -asyncapi: "2.0.0" -id: "urn:com:http:server" -info: - title: Http Application - version: "1.0.0" - description: Http Application - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 -servers: - production: - url: localhost:8080 - description: Development server - protocol: http -channels: - first: - description: A message channel - subscribe: - summary: Get messages - message: - $ref: "#/components/messages/message" - publish: - summary: Send messages - message: - $ref: "#/components/messages/message" - traits: - - bindings: - flogo-kafka: - partitions: "0" - offset: 0 -components: - messages: - message: - name: message - summary: A message - contentType: application/json - payload: - $ref: "#/components/schemas/message" - schemas: - message: - type: object - properties: - name: - type: string - age: - type: integer diff --git a/workflowproj/testdata/valid-camelroute.json b/workflowproj/testdata/valid-camelroute.json deleted file mode 100644 index 1c4f187b..00000000 --- a/workflowproj/testdata/valid-camelroute.json +++ /dev/null @@ -1,393 +0,0 @@ -[ - { - "rest": { - "path": "/api/v3", - "put": [ - { - "consumes": "application/json,application/xml", - "id": "updatePet", - "path": "/pet", - "param": [ - { - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:updatePet" - } - }, - { - "consumes": "*/*", - "id": "updateUser", - "path": "/user/{username}", - "param": [ - { - "dataType": "string", - "name": "username", - "required": true, - "type": "path" - }, - { - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:updateUser" - } - } - ], - "post": [ - { - "consumes": "application/json,application/xml", - "id": "addPet", - "path": "/pet", - "param": [ - { - "dataType": "boolean", - "defaultValue": "false", - "description": "Verbose data", - "name": "verbose", - "required": false, - "type": "query" - }, - { - "description": "Pet object that needs to be added to the store", - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:addPet" - } - }, - { - "consumes": "application/x-www-form-urlencoded", - "id": "updatePetWithForm", - "path": "/pet/{petId}", - "param": [ - { - "dataType": "integer", - "description": "ID of pet that needs to be updated", - "name": "petId", - "required": true, - "type": "path" - }, - { - "dataType": "string", - "description": "Updated name of the pet", - "name": "name", - "required": true, - "type": "formData" - }, - { - "dataType": "string", - "description": "Updated status of the pet", - "name": "status", - "required": true, - "type": "formData" - } - ], - "to": { - "uri": "direct:updatePetWithForm" - } - }, - { - "consumes": "multipart/form-data", - "id": "uploadFile", - "produces": "application/json", - "path": "/pet/{petId}/uploadImage", - "param": [ - { - "dataType": "integer", - "description": "ID of pet to update", - "name": "petId", - "required": true, - "type": "path" - }, - { - "dataType": "string", - "description": "Additional data to pass to server", - "name": "additionalMetadata", - "required": true, - "type": "formData" - }, - { - "dataType": "string", - "description": "file to upload", - "name": "file", - "required": true, - "type": "formData" - } - ], - "to": { - "uri": "direct:uploadFile" - } - }, - { - "consumes": "*/*", - "id": "placeOrder", - "produces": "application/xml,application/json", - "path": "/store/order", - "param": [ - { - "description": "order placed for purchasing the pet", - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:placeOrder" - } - }, - { - "consumes": "*/*", - "id": "createUser", - "path": "/user", - "description": "This can only be done by the logged in user.", - "param": [ - { - "description": "Created user object", - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:createUser" - } - }, - { - "consumes": "*/*", - "id": "createUsersWithArrayInput", - "path": "/user/createWithArray", - "param": [ - { - "description": "List of user object", - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:createUsersWithArrayInput" - } - }, - { - "consumes": "*/*", - "id": "createUsersWithListInput", - "path": "/user/createWithList", - "param": [ - { - "description": "List of user object", - "name": "body", - "required": true, - "type": "body" - } - ], - "to": { - "uri": "direct:createUsersWithListInput" - } - } - ], - "get": [ - { - "id": "findPetsByStatus", - "produces": "application/xml,application/json", - "path": "/pet/findByStatus", - "description": "Multiple status values can be provided with comma separated strings", - "param": [ - { - "arrayType": "string", - "collectionFormat": "multi", - "dataType": "array", - "description": "Status values that need to be considered for filter", - "name": "status", - "required": true, - "type": "query" - } - ], - "to": { - "uri": "direct:findPetsByStatus" - } - }, - { - "id": "findPetsByTags", - "produces": "application/xml,application/json", - "path": "/pet/findByTags", - "description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", - "param": [ - { - "arrayType": "string", - "collectionFormat": "multi", - "dataType": "array", - "description": "Tags to filter by", - "name": "tags", - "required": true, - "type": "query" - } - ], - "to": { - "uri": "direct:findPetsByTags" - } - }, - { - "id": "getPetById", - "produces": "application/xml,application/json", - "path": "/pet/{petId}", - "description": "Returns a single pet", - "param": [ - { - "dataType": "integer", - "description": "ID of pet to return", - "name": "petId", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:getPetById" - } - }, - { - "id": "getInventory", - "produces": "application/json", - "path": "/store/inventory", - "description": "Returns a map of status codes to quantities", - "to": { - "uri": "direct:getInventory" - } - }, - { - "id": "getOrderById", - "produces": "application/xml,application/json", - "path": "/store/order/{orderId}", - "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", - "param": [ - { - "dataType": "integer", - "description": "ID of pet that needs to be fetched", - "name": "orderId", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:getOrderById" - } - }, - { - "id": "loginUser", - "produces": "application/xml,application/json", - "path": "/user/login", - "param": [ - { - "dataType": "string", - "description": "The user name for login", - "name": "username", - "required": true, - "type": "query" - }, - { - "dataType": "string", - "description": "The password for login in clear text", - "name": "password", - "required": true, - "type": "query" - } - ], - "to": { - "uri": "direct:loginUser" - } - }, - { - "id": "logoutUser", - "path": "/user/logout", - "to": { - "uri": "direct:logoutUser" - } - }, - { - "id": "getUserByName", - "produces": "application/xml,application/json", - "path": "/user/{username}", - "param": [ - { - "dataType": "string", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "name": "username", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:getUserByName" - } - } - ], - "delete": [ - { - "id": "deletePet", - "path": "/pet/{petId}", - "param": [ - { - "dataType": "string", - "name": "api_key", - "required": false, - "type": "header" - }, - { - "dataType": "integer", - "description": "Pet id to delete", - "name": "petId", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:deletePet" - } - }, - { - "id": "deleteOrder", - "path": "/store/order/{orderId}", - "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", - "param": [ - { - "dataType": "integer", - "description": "ID of the order that needs to be deleted", - "name": "orderId", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:deleteOrder" - } - }, - { - "id": "deleteUser", - "path": "/user/{username}", - "description": "This can only be done by the logged in user.", - "param": [ - { - "dataType": "string", - "description": "The name that needs to be deleted", - "name": "username", - "required": true, - "type": "path" - } - ], - "to": { - "uri": "direct:deleteUser" - } - } - ] - } - } -] diff --git a/workflowproj/testdata/valid-camelroute.yaml b/workflowproj/testdata/valid-camelroute.yaml deleted file mode 100644 index 2b56189c..00000000 --- a/workflowproj/testdata/valid-camelroute.yaml +++ /dev/null @@ -1,275 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Borrowed from https://github.com/apache/camel/tree/camel-3.20.5/dsl/camel-yaml-dsl/camel-yaml-dsl -- rest: - path: "/api/v3" - put: - - consumes: "application/json,application/xml" - id: "updatePet" - path: "/pet" - param: - - name: "body" - required: true - type: "body" - to: - uri: "direct:updatePet" - - consumes: "*/*" - id: "updateUser" - path: "/user/{username}" - param: - - dataType: "string" - name: "username" - required: true - type: "path" - - name: "body" - required: true - type: "body" - to: - uri: "direct:updateUser" - post: - - consumes: "application/json,application/xml" - id: "addPet" - path: "/pet" - param: - - dataType: "boolean" - defaultValue: "false" - description: "Verbose data" - name: "verbose" - required: false - type: "query" - - description: "Pet object that needs to be added to the store" - name: "body" - required: true - type: "body" - to: - uri: "direct:addPet" - - consumes: "application/x-www-form-urlencoded" - id: "updatePetWithForm" - path: "/pet/{petId}" - param: - - dataType: "integer" - description: "ID of pet that needs to be updated" - name: "petId" - required: true - type: "path" - - dataType: "string" - description: "Updated name of the pet" - name: "name" - required: true - type: "formData" - - dataType: "string" - description: "Updated status of the pet" - name: "status" - required: true - type: "formData" - to: - uri: "direct:updatePetWithForm" - - consumes: "multipart/form-data" - id: "uploadFile" - produces: "application/json" - path: "/pet/{petId}/uploadImage" - param: - - dataType: "integer" - description: "ID of pet to update" - name: "petId" - required: true - type: "path" - - dataType: "string" - description: "Additional data to pass to server" - name: "additionalMetadata" - required: true - type: "formData" - - dataType: "string" - description: "file to upload" - name: "file" - required: true - type: "formData" - to: - uri: "direct:uploadFile" - - consumes: "*/*" - id: "placeOrder" - produces: "application/xml,application/json" - path: "/store/order" - param: - - description: "order placed for purchasing the pet" - name: "body" - required: true - type: "body" - to: - uri: "direct:placeOrder" - - consumes: "*/*" - id: "createUser" - path: "/user" - description: "This can only be done by the logged in user." - param: - - description: "Created user object" - name: "body" - required: true - type: "body" - to: - uri: "direct:createUser" - - consumes: "*/*" - id: "createUsersWithArrayInput" - path: "/user/createWithArray" - param: - - description: "List of user object" - name: "body" - required: true - type: "body" - to: - uri: "direct:createUsersWithArrayInput" - - consumes: "*/*" - id: "createUsersWithListInput" - path: "/user/createWithList" - param: - - description: "List of user object" - name: "body" - required: true - type: "body" - to: - uri: "direct:createUsersWithListInput" - get: - - id: "findPetsByStatus" - produces: "application/xml,application/json" - path: "/pet/findByStatus" - description: "Multiple status values can be provided with comma separated strings" - param: - - arrayType: "string" - collectionFormat: "multi" - dataType: "array" - description: "Status values that need to be considered for filter" - name: "status" - required: true - type: "query" - to: - uri: "direct:findPetsByStatus" - - id: "findPetsByTags" - produces: "application/xml,application/json" - path: "/pet/findByTags" - description: "Muliple tags can be provided with comma separated strings. Use\ - \ tag1, tag2, tag3 for testing." - param: - - arrayType: "string" - collectionFormat: "multi" - dataType: "array" - description: "Tags to filter by" - name: "tags" - required: true - type: "query" - to: - uri: "direct:findPetsByTags" - - id: "getPetById" - produces: "application/xml,application/json" - path: "/pet/{petId}" - description: "Returns a single pet" - param: - - dataType: "integer" - description: "ID of pet to return" - name: "petId" - required: true - type: "path" - to: - uri: "direct:getPetById" - - id: "getInventory" - produces: "application/json" - path: "/store/inventory" - description: "Returns a map of status codes to quantities" - to: - uri: "direct:getInventory" - - id: "getOrderById" - produces: "application/xml,application/json" - path: "/store/order/{orderId}" - description: "For valid response try integer IDs with value >= 1 and <= 10.\ - \ Other values will generated exceptions" - param: - - dataType: "integer" - description: "ID of pet that needs to be fetched" - name: "orderId" - required: true - type: "path" - to: - uri: "direct:getOrderById" - - id: "loginUser" - produces: "application/xml,application/json" - path: "/user/login" - param: - - dataType: "string" - description: "The user name for login" - name: "username" - required: true - type: "query" - - dataType: "string" - description: "The password for login in clear text" - name: "password" - required: true - type: "query" - to: - uri: "direct:loginUser" - - id: "logoutUser" - path: "/user/logout" - to: - uri: "direct:logoutUser" - - id: "getUserByName" - produces: "application/xml,application/json" - path: "/user/{username}" - param: - - dataType: "string" - description: "The name that needs to be fetched. Use user1 for testing. " - name: "username" - required: true - type: "path" - to: - uri: "direct:getUserByName" - delete: - - id: "deletePet" - path: "/pet/{petId}" - param: - - dataType: "string" - name: "api_key" - required: false - type: "header" - - dataType: "integer" - description: "Pet id to delete" - name: "petId" - required: true - type: "path" - to: - uri: "direct:deletePet" - - id: "deleteOrder" - path: "/store/order/{orderId}" - description: "For valid response try integer IDs with positive integer value.\ - \ Negative or non-integer values will generate API errors" - param: - - dataType: "integer" - description: "ID of the order that needs to be deleted" - name: "orderId" - required: true - type: "path" - to: - uri: "direct:deleteOrder" - - id: "deleteUser" - path: "/user/{username}" - description: "This can only be done by the logged in user." - param: - - dataType: "string" - description: "The name that needs to be deleted" - name: "username" - required: true - type: "path" - to: - uri: "direct:deleteUser" diff --git a/workflowproj/testdata/valid-openapi.json b/workflowproj/testdata/valid-openapi.json deleted file mode 100644 index 477a3171..00000000 --- a/workflowproj/testdata/valid-openapi.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Generated API", - "version": "1.0" - }, - "paths": { - "/": { - "post": { - "operationId": "doOperation", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubtractionOperation" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "difference": { - "format": "float", - "type": "number" - } - } - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SubtractionOperation": { - "type": "object", - "properties": { - "leftElement": { - "format": "float", - "type": "number" - }, - "rightElement": { - "format": "float", - "type": "number" - } - } - } - } - } -} diff --git a/workflowproj/testdata/valid-openapi.yaml b/workflowproj/testdata/valid-openapi.yaml deleted file mode 100644 index 7480df27..00000000 --- a/workflowproj/testdata/valid-openapi.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - ---- -openapi: 3.0.3 -info: - title: Generated API - version: "1.0" -paths: - /: - post: - operationId: doOperation - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/SubtractionOperation" - responses: - "200": - description: OK - content: - application/json: - schema: - type: object - properties: - difference: - format: float - type: number -components: - schemas: - SubtractionOperation: - type: object - properties: - leftElement: - format: float - type: number - rightElement: - format: float - type: number diff --git a/workflowproj/testdata/workflows/application.properties b/workflowproj/testdata/workflows/application.properties deleted file mode 100644 index 8bec78e2..00000000 --- a/workflowproj/testdata/workflows/application.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -quarkus.log.level=DEBUG -mp.messaging.incoming.kogito_incoming_stream.connector=quarkus-http -mp.messaging.incoming.kogito_incoming_stream.path=/ - -quarkus.devservices.enabled=false \ No newline at end of file diff --git a/workflowproj/testdata/workflows/secret.properties b/workflowproj/testdata/workflows/secret.properties deleted file mode 100644 index 5b302b06..00000000 --- a/workflowproj/testdata/workflows/secret.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -MY_USER_PASSWORD=Super$ecretP@ssw0rd! -DATABASE_URL=https://secure.example.com -API_KEY=12345-ABCDE-67890-FGHIJ -ANOTHER_KEY=ThisIs@Complex#Value123 -DB_ROOT_PASSWORD=!P@$$w0rd_123# -JWT_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 -ENCRYPTION_KEY=5up3r-53cr37-K3y! -KEY_WITH_NUMBERS_123=ValueWith123Numbers -SIMPLE_KEY=Simple_Value_2024 diff --git a/workflowproj/testdata/workflows/specs/workflow-service-openapi.json b/workflowproj/testdata/workflows/specs/workflow-service-openapi.json deleted file mode 100644 index fd1b74b0..00000000 --- a/workflowproj/testdata/workflows/specs/workflow-service-openapi.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Score Service", - "version": "1.0.0" - }, - "servers": [ - { - "url": "https://kogito-demo-scores-kverlaen-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com/" - } - ], - "paths": { - "/scores": { - "get": { - "operationId": "countWinners", - "responses": { - "200": { - "description": "OK", - "content": { - "text/plain": { - "schema": { - "format": "int64", - "type": "integer" - } - } - } - } - } - }, - "post": { - "operationId": "isWinner", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScoreResult" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "ScoreResult": { - "type": "object", - "properties": { - "result": { - "type": "boolean" - } - } - } - } - } -} diff --git a/workflowproj/testdata/workflows/specs/workflow-service-schema.json b/workflowproj/testdata/workflows/specs/workflow-service-schema.json deleted file mode 100644 index 5e4544ee..00000000 --- a/workflowproj/testdata/workflows/specs/workflow-service-schema.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "name": { - "type": "string" - } - }, - "required": ["name"] -} diff --git a/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json b/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json deleted file mode 100644 index 978f8fea..00000000 --- a/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "states": [ - { - "name": "HelloWorld", - "type": "inject", - "data": { - "message": "Hello World" - }, - "end": true - } - ] -} diff --git a/workflowproj/testdata/workflows/workflow-minimal.sw.json b/workflowproj/testdata/workflows/workflow-minimal.sw.json deleted file mode 100644 index 9ffadb52..00000000 --- a/workflowproj/testdata/workflows/workflow-minimal.sw.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "hello", - "specVersion": "0.8.0", - "name": "Hello World", - "start": "HelloWorld", - "states": [ - { - "name": "HelloWorld", - "type": "inject", - "data": { - "message": "Hello World" - }, - "end": true - } - ] -} diff --git a/workflowproj/testdata/workflows/workflow-service.sw.json b/workflowproj/testdata/workflows/workflow-service.sw.json deleted file mode 100644 index ab71201f..00000000 --- a/workflowproj/testdata/workflows/workflow-service.sw.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id": "service", - "specVersion": "0.8.0", - "name": "Hello Service", - "start": "Service", - "dataInputSchema": "specs/workflow-service-schema.json", - "functions": [ - { - "name": "isWinner", - "operation": "specs/workflow-service-openapi.json#isWinner", - "type": "rest" - } - ], - "states": [ - { - "name": "Service", - "type": "operation", - "actions": [ - { - "name": "CallService", - "functionRef": { - "refName": "isWinner", - "arguments": {} - } - } - ], - "end": true - } - ] -} diff --git a/workflowproj/workflowproj.go b/workflowproj/workflowproj.go deleted file mode 100644 index 3fa1a402..00000000 --- a/workflowproj/workflowproj.go +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "context" - "fmt" - "io" - "regexp" - "sort" - "strings" - - "github.com/magiconair/properties" - - "github.com/pkg/errors" - "github.com/serverlessworkflow/sdk-go/v2/model" - "github.com/serverlessworkflow/sdk-go/v2/parser" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/kubernetes/scheme" - - "github.com/kubesmarts/logic-operator/api/metadata" - operatorapi "github.com/kubesmarts/logic-operator/api/v1alpha08" -) - -var _ WorkflowProjectHandler = &workflowProjectHandler{} - -// defaultResourcePath is the default resource path to add to the generated ConfigMaps -const defaultResourcePath = "specs" - -// WorkflowProjectHandler is the description of the handler interface. -// A handler can generate Kubernetes manifests to deploy a new SonataFlow project in the cluster -type WorkflowProjectHandler interface { - // Named overwrites the workflow ID. The handler will use this name instead to generate the manifests name. - // Remember that together with the Namespace, the Name is the unique key of a Kubernetes object. - Named(name string) WorkflowProjectHandler - // Profile overrides the default profile (dev) in the generated SonataFlow manifest - Profile(profile metadata.ProfileType) WorkflowProjectHandler - // WithWorkflow reader for a file or the content stream of a workflow definition. - WithWorkflow(reader io.Reader) WorkflowProjectHandler - // WithAppProperties reader for a file or the content stream of a workflow application properties. - WithAppProperties(reader io.Reader) WorkflowProjectHandler - // WithSecretProperties reader for a file or the content stream of a workflow application properties. - WithSecretProperties(reader io.Reader) WorkflowProjectHandler - // AddResource reader for a file or the content stream of any resource needed by the workflow. E.g. an OpenAPI specification file. - // Name is required, should match the workflow function definition. - AddResource(name string, reader io.Reader) WorkflowProjectHandler - // AddResourceAt same as AddResource, but defines the path instead of using the default. - AddResourceAt(name, path string, reader io.Reader) WorkflowProjectHandler - // SaveAsKubernetesManifests saves the project in the given file system path in YAML format. - SaveAsKubernetesManifests(path string) error - // AsObjects returns a reference to the WorkflowProject holding the Kubernetes Manifests based on your files. - AsObjects() (*WorkflowProject, error) - // Image overrides the default image in the generated SonataFlow manifest - Image(image string) WorkflowProjectHandler -} - -// WorkflowProject is a structure to hold every Kubernetes object generated by the given WorkflowProjectHandler handler. -type WorkflowProject struct { - // Workflow the workflow definition - Workflow *operatorapi.SonataFlow - // Properties the application properties for the workflow - Properties *corev1.ConfigMap - //SecretProperties the secret properties for the workflow - SecretProperties *corev1.Secret - // Resources any resource that this workflow requires, like an OpenAPI specification file. - Resources []*corev1.ConfigMap -} - -type resource struct { - name string - contents io.Reader -} - -// New is the entry point for this package. -// You can create a new handler with the given namespace, meaning that every manifest generated will use this namespace. -func New(namespace string) WorkflowProjectHandler { - s := scheme.Scheme - utilruntime.Must(operatorapi.AddToScheme(s)) - utilruntime.Must(corev1.AddToScheme(s)) - return &workflowProjectHandler{ - scheme: s, - namespace: namespace, - rawResources: map[string][]*resource{}, - } -} - -type workflowProjectHandler struct { - name string - namespace string - profile metadata.ProfileType - scheme *runtime.Scheme - project WorkflowProject - rawWorkflow io.Reader - rawAppProperties io.Reader - rawSecretProperties io.Reader - rawResources map[string][]*resource - parsed bool -} - -func (w *workflowProjectHandler) Named(name string) WorkflowProjectHandler { - w.name = strings.ToLower(name) - w.parsed = false - return w -} - -func (w *workflowProjectHandler) Profile(profile metadata.ProfileType) WorkflowProjectHandler { - w.profile = profile - w.parsed = false - return w -} - -func (w *workflowProjectHandler) WithWorkflow(reader io.Reader) WorkflowProjectHandler { - w.rawWorkflow = reader - w.parsed = false - return w -} - -func (w *workflowProjectHandler) WithAppProperties(reader io.Reader) WorkflowProjectHandler { - w.rawAppProperties = reader - w.parsed = false - return w -} - -func (w *workflowProjectHandler) WithSecretProperties(reader io.Reader) WorkflowProjectHandler { - w.rawSecretProperties = reader - w.parsed = false - return w -} - -func (w *workflowProjectHandler) AddResource(name string, reader io.Reader) WorkflowProjectHandler { - return w.AddResourceAt(name, defaultResourcePath, reader) -} - -func (w *workflowProjectHandler) AddResourceAt(name, path string, reader io.Reader) WorkflowProjectHandler { - for _, r := range w.rawResources[path] { - if r.name == name { - r.contents = reader - return w - } - } - w.rawResources[path] = append(w.rawResources[path], &resource{name: name, contents: reader}) - w.parsed = false - return w -} - -func (w *workflowProjectHandler) SaveAsKubernetesManifests(path string) error { - if err := ensurePath(path); err != nil { - return err - } - if err := w.parseRawProject(); err != nil { - return err - } - fileCount := 0 - if w.project.Properties != nil { - fileCount++ - if err := saveAsKubernetesManifest(w.project.Properties, path, fileCount); err != nil { - return err - } - } - if w.project.SecretProperties != nil { - fileCount++ - if err := saveAsKubernetesManifest(w.project.SecretProperties, path, fileCount); err != nil { - return err - } - } - for _, r := range w.project.Resources { - fileCount++ - if err := saveAsKubernetesManifest(r, path, fileCount); err != nil { - return err - } - } - fileCount++ - if err := saveAsKubernetesManifest(w.project.Workflow, path, fileCount); err != nil { - return err - } - return nil -} - -func (w *workflowProjectHandler) AsObjects() (*WorkflowProject, error) { - if err := w.parseRawProject(); err != nil { - return nil, err - } - return &w.project, nil -} - -func (w *workflowProjectHandler) parseRawProject() error { - if w.parsed { - return nil - } - if err := w.sanityCheck(); err != nil { - return err - } - if err := w.parseRawWorkflow(); err != nil { - return err - } - if err := w.parseRawAppProperties(); err != nil { - return err - } - if err := w.parseRawSecretProperties(); err != nil { - return err - } - if err := w.parseRawResources(); err != nil { - return err - } - w.parsed = true - return nil -} - -func (w *workflowProjectHandler) sanityCheck() error { - if w.rawWorkflow == nil { - return errors.New("A workflow reader pointer is required when building Workflow projects") - } - return nil -} - -func (w *workflowProjectHandler) parseRawWorkflow() error { - workflowContents, err := io.ReadAll(w.rawWorkflow) - if err != nil { - return err - } - var workflowDef *model.Workflow - // TODO: add this to the SDK, also an input from io.Reader - workflowDef, err = parser.FromJSONSource(workflowContents) - if err != nil { - workflowDef, err = parser.FromYAMLSource(workflowContents) - if err != nil { - return errors.Errorf("Failed to parse the workflow either as a JSON or as a YAML file: %+v", err) - } - } - - if len(w.name) == 0 { - w.name = strings.ToLower(workflowDef.ID) - } - - w.project.Workflow, err = operatorapi.FromCNCFWorkflow(workflowDef, context.TODO()) - w.project.Workflow.Name = w.name - w.project.Workflow.Namespace = w.namespace - profile := metadata.DevProfile - if len(w.profile) > 0 { - profile = w.profile - } - SetWorkflowProfile(w.project.Workflow, profile) - SetMergedLabels(w.project.Workflow, w.project.Workflow) - if err = SetTypeToObject(w.project.Workflow, w.scheme); err != nil { - return err - } - - return nil -} - -func (w *workflowProjectHandler) parseRawAppProperties() error { - if w.rawAppProperties == nil { - return nil - } - appPropsContent, err := io.ReadAll(w.rawAppProperties) - if err != nil { - return err - } - w.project.Properties = CreateNewUserPropsConfigMap(w.project.Workflow) - w.project.Properties.Data[ApplicationPropertiesFileName] = string(appPropsContent) - if err = SetTypeToObject(w.project.Properties, w.scheme); err != nil { - return err - } - return nil -} - -func (w *workflowProjectHandler) parseRawSecretProperties() error { - if w.rawSecretProperties == nil { - return nil - } - secretPropsContent, err := io.ReadAll(w.rawSecretProperties) - if err != nil { - return fmt.Errorf("Failed to read secret properties: %w", err) - } - secrets, err := properties.Load(secretPropsContent, properties.UTF8) - if err != nil { - return fmt.Errorf("Failed to load secret properties: %w", err) - } - if len(secrets.Map()) == 0 { - return nil //Do not create a secret if there are no secrets - } - - w.project.SecretProperties = CreateNewSecretPropsConfigMap(w.project.Workflow) - w.project.SecretProperties.StringData = map[string]string{} - for key, value := range secrets.Map() { - normalizedEnvNames, err := normalizeEnvNames(key) - if err != nil { - return err - } - for _, normalizedEnvName := range normalizedEnvNames { - w.project.SecretProperties.StringData[key] = value - env := corev1.EnvVar{ - Name: normalizedEnvName, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: w.project.SecretProperties.Name, - }, - Key: key, - }, - }, - } - w.project.Workflow.Spec.PodTemplate.Container.Env = append(w.project.Workflow.Spec.PodTemplate.Container.Env, env) - } - } - - if err = SetTypeToObject(w.project.SecretProperties, w.scheme); err != nil { - return err - } - return nil -} - -func (w *workflowProjectHandler) parseRawResources() error { - if len(w.rawResources) == 0 { - return nil - } - - resourceCount := 1 - paths := []string{} - for k := range w.rawResources { - paths = append(paths, k) - } - // Sort the paths to generate a deterministric list of files. - // Without sorting Golang map iteration on the strings is inconsistent because - // iteration order is not specified, so each time we could get 01-configmap-NAME-resources.yaml - // with schemas, and the next time with subflows, or other way round. - sort.Strings(paths) - for _, path := range paths { - // For better usability also convenience we add the 'path' from which the config map is taken - // so the config map file will have a meaningful name like - // 01-configmap-NAME-resources-specs.yaml or -subflow.yaml or -schemas.yaml - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Namespace: w.namespace, Name: fmt.Sprintf("%02d-%s-resources-%s", resourceCount, w.name, path)}, - Data: map[string]string{}, - } - - for _, r := range w.rawResources[path] { - contents, err := io.ReadAll(r.contents) - if err != nil { - return err - } - if len(contents) == 0 { - return errors.Errorf("Content for the resource %s is empty. Can't add an empty resource to the workflow project", r.name) - } - cm.Data[r.name] = string(contents) - } - - if err := w.addResourceConfigMapToProject(cm, path); err != nil { - return err - } - resourceCount++ - } - - return nil -} - -func (w *workflowProjectHandler) addResourceConfigMapToProject(cm *corev1.ConfigMap, path string) error { - if cm.Data != nil { - if err := SetTypeToObject(cm, w.scheme); err != nil { - return err - } - w.project.Workflow.Spec.Resources.ConfigMaps = append(w.project.Workflow.Spec.Resources.ConfigMaps, - operatorapi.ConfigMapWorkflowResource{ConfigMap: corev1.LocalObjectReference{Name: cm.Name}, WorkflowPath: path}) - w.project.Resources = append(w.project.Resources, cm) - } - return nil -} -func (w *workflowProjectHandler) Image(image string) WorkflowProjectHandler { - w.project.Workflow.Spec.PodTemplate.Container.Image = image - return w -} - -// IsDevProfile detects if the workflow is using the Dev profile or not -func IsDevProfile(workflow *operatorapi.SonataFlow) bool { - return isProfile(workflow, metadata.DevProfile) -} - -// IsGitOpsProfile detects if the workflow is using the GitOps profile or not -func IsGitOpsProfile(workflow *operatorapi.SonataFlow) bool { - return isProfile(workflow, metadata.GitOpsProfile) -} - -func isProfile(workflow *operatorapi.SonataFlow, profileType metadata.ProfileType) bool { - profile := workflow.Annotations[metadata.Profile] - if len(profile) == 0 { - return false - } - return metadata.ProfileType(profile) == profileType -} - -var envProfilesExpr = regexp.MustCompile(`^%([A-Za-z0-9_-]+(?:,[A-Za-z0-9_-]+)*)\.(.+)$`) - -func normalizeEnvNames(names string) ([]string, error) { - matches := envProfilesExpr.FindStringSubmatch(names) - if matches == nil { - if normalized, err := normalizeEnvName(names); err != nil { - return nil, err - } else { - return []string{normalized}, nil - } - } else { - profiles := strings.Split(matches[1], ",") - propertyKey := matches[2] - var result []string - for _, profile := range profiles { - normalized, err := normalizeEnvName("%" + profile + "_" + propertyKey) - if err != nil { - return nil, err - } - result = append(result, normalized) - } - return result, nil - } -} - -func normalizeEnvName(original string) (string, error) { - name := original - name = strings.TrimSpace(name) - - replacer := strings.NewReplacer( - " ", "_", - "-", "_", - ".", "_", - "\"", "_", - "'", "_", - "[", "_", - "]", "_", - "%", "_", - ) - name = replacer.Replace(name) - name = strings.ToUpper(name) - - if strings.HasSuffix(name, "_") { - name = name[:len(name)-1] - } - - validName := regexp.MustCompile(`^[A-Z0-9_]+$`) - if !validName.MatchString(name) { - return "", fmt.Errorf("invalid environment variable name: %s (must only contain A-Z, 0-9, and _)", original) - } - - return name, nil -} diff --git a/workflowproj/workflowproj_test.go b/workflowproj/workflowproj_test.go deleted file mode 100644 index f0357f50..00000000 --- a/workflowproj/workflowproj_test.go +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 workflowproj - -import ( - "fmt" - "io" - "os" - "path" - "sort" - "strings" - "testing" - - "github.com/magiconair/properties" - - "k8s.io/apimachinery/pkg/runtime/schema" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes/scheme" - - "github.com/kubesmarts/logic-operator/api/metadata" -) - -func Test_Handler_WorkflowMinimal(t *testing.T) { - proj, err := New("default").WithWorkflow(getWorkflowMinimal()).AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj) - assert.Equal(t, "hello", proj.Workflow.Name) - assert.Equal(t, string(metadata.DevProfile), proj.Workflow.Annotations[metadata.Profile]) -} - -func Test_Handler_WorkflowMinimalInvalid(t *testing.T) { - proj, err := New("default"). - WithWorkflow(getWorkflowMinimalInvalid()). - AsObjects() - assert.Error(t, err) - assert.Nil(t, proj) -} - -func Test_Handler_WorkflowMinimalAndProps(t *testing.T) { - proj, err := New("default"). - Named("minimal"). - Profile(metadata.PreviewProfile). - WithWorkflow(getWorkflowMinimal()). - WithAppProperties(getWorkflowProperties()). - AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - assert.NotNil(t, proj.Properties) - assert.Equal(t, "minimal", proj.Workflow.Name) - assert.Equal(t, "minimal-props", proj.Properties.Name) - assert.NotEmpty(t, proj.Properties.Data["application.properties"]) - assert.Equal(t, string(metadata.PreviewProfile), proj.Workflow.Annotations[metadata.Profile]) - assert.NotEmpty(t, proj.Properties.Data) -} - -func Test_Handler_WorkflowMinimalAndPropsAndSpec(t *testing.T) { - proj, err := New("default"). - WithWorkflow(getWorkflowMinimal()). - WithAppProperties(getWorkflowProperties()). - AddResource("myopenapi.json", getSpecOpenApi()). - AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - assert.NotNil(t, proj.Workflow.ObjectMeta) - assert.Equal(t, proj.Workflow.ObjectMeta.Labels, map[string]string{ - "app": "hello", - "sonataflow.org/workflow-app": "hello", - "sonataflow.org/workflow-namespace": "default", - "app.kubernetes.io/name": "hello", - "app.kubernetes.io/component": "serverless-workflow", - "app.kubernetes.io/managed-by": "sonataflow-operator", - }) - assert.NotNil(t, proj.Properties) - assert.NotEmpty(t, proj.Resources) - assert.Equal(t, "hello", proj.Workflow.Name) - assert.Equal(t, "hello-props", proj.Properties.Name) - assert.NotEmpty(t, proj.Properties.Data) - assert.Equal(t, 1, len(proj.Resources)) - assert.Equal(t, "01-hello-resources-specs", proj.Resources[0].Name) - assert.Equal(t, proj.Workflow.Spec.Resources.ConfigMaps[0].ConfigMap.Name, proj.Resources[0].Name) - -} - -func Test_Handler_WorkflowMinimalAndPropsAndSpecAndGeneric(t *testing.T) { - proj, err := New("default"). - WithWorkflow(getWorkflowMinimal()). - WithAppProperties(getWorkflowProperties()). - AddResource("myopenapi.json", getSpecOpenApi()). - AddResource("myopenapi.json", getSpecOpenApi()). - AddResource("myopenapi2.json", getSpecOpenApi()). - AddResourceAt("input.json", "files", getSpecGeneric()). - AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - assert.NotNil(t, proj.Properties) - assert.NotEmpty(t, proj.Resources) - sort.Slice(proj.Resources, func(i, j int) bool { - return proj.Resources[i].Name < proj.Resources[j].Name - }) - sort.Slice(proj.Workflow.Spec.Resources.ConfigMaps, func(i, j int) bool { - return proj.Workflow.Spec.Resources.ConfigMaps[i].ConfigMap.Name < proj.Workflow.Spec.Resources.ConfigMaps[j].ConfigMap.Name - }) - - assert.Equal(t, "hello", proj.Workflow.Name) - assert.Equal(t, "hello-props", proj.Properties.Name) - assert.NotEmpty(t, proj.Properties.Data) - assert.Equal(t, 2, len(proj.Resources)) - assert.Equal(t, "01-hello-resources-files", proj.Resources[0].Name) - assert.Equal(t, "02-hello-resources-specs", proj.Resources[1].Name) - assert.Equal(t, proj.Workflow.Spec.Resources.ConfigMaps[0].ConfigMap.Name, proj.Resources[0].Name) - assert.Equal(t, proj.Workflow.Spec.Resources.ConfigMaps[1].ConfigMap.Name, proj.Resources[1].Name) - data, err := getResourceDataWithFileName(proj.Resources, "myopenapi.json") - assert.NoError(t, err) - assert.NotEmpty(t, data) - data, err = getResourceDataWithFileName(proj.Resources, "input.json") - assert.NoError(t, err) - assert.NotEmpty(t, data) -} - -func Test_Handler_WorkflowMinimalAndSecrets(t *testing.T) { - type env struct { - key string - secretKeyRefName string - } - proj, err := New("default"). - Named("minimal"). - Profile(metadata.PreviewProfile). - WithWorkflow(getWorkflowMinimal()). - WithSecretProperties(getWorkflowSecretProperties()). - AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - assert.NotNil(t, proj.SecretProperties) - assert.Equal(t, "minimal", proj.Workflow.Name) - assert.Equal(t, "minimal-secrets", proj.SecretProperties.Name) - assert.NotEmpty(t, proj.SecretProperties.StringData) - - secretPropsContent, err := io.ReadAll(getWorkflowSecretProperties()) - assert.NoError(t, err) - secrets, err := properties.Load(secretPropsContent, properties.UTF8) - assert.NoError(t, err) - envs := map[string]env{} - - for _, value := range proj.Workflow.Spec.PodTemplate.Container.Env { - envs[value.Name] = env{key: value.ValueFrom.SecretKeyRef.Key, secretKeyRefName: value.ValueFrom.SecretKeyRef.Name} - } - - for k, v := range secrets.Map() { - assert.Equal(t, v, proj.SecretProperties.StringData[k]) - normalized, err := normalizeEnvNames(k) - for _, value := range normalized { - assert.NoError(t, err) - env, exists := envs[value] - assert.True(t, exists) - assert.Equal(t, k, env.key) - assert.Equal(t, proj.SecretProperties.Name, env.secretKeyRefName) - } - - } -} - -func getResourceDataWithFileName(cms []*corev1.ConfigMap, fileName string) (string, error) { - for i := range cms { - if data, ok := cms[i].Data[fileName]; ok { - return data, nil - } - } - return "", fmt.Errorf("No configmap found with data containing filename %s", fileName) -} - -func Test_Handler_WorklflowServiceAndPropsAndSpec_SaveAs(t *testing.T) { - handler := New("default"). - WithWorkflow(getWorkflowService()). - WithAppProperties(getWorkflowProperties()). - AddResource("myopenapi.json", getSpecOpenApi()). - AddResourceAt("schema.json", "files", getSpecGeneric()) - proj, err := handler.AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - assert.NotNil(t, proj.Properties) - assert.NotEmpty(t, proj.Resources) - - tmpPath, err := os.MkdirTemp("", "*-test") - assert.NoError(t, err) - defer os.RemoveAll(tmpPath) - - assert.NoError(t, handler.SaveAsKubernetesManifests(tmpPath)) - files, err := os.ReadDir(tmpPath) - assert.NoError(t, err) - assert.Len(t, files, 4) - - expectedFiles := []string{ - "01-configmap_service-props.yaml", - "02-configmap_01-service-resources-files.yaml", - "03-configmap_02-service-resources-specs.yaml", - "04-sonataflow_service.yaml", - } - expectedKinds := []schema.GroupVersionKind{ - {Group: "", Version: "v1", Kind: "ConfigMap"}, - {Group: "", Version: "v1", Kind: "ConfigMap"}, - {Group: "", Version: "v1", Kind: "ConfigMap"}, - {Group: "sonataflow.org", Version: "v1alpha08", Kind: "SonataFlow"}, - } - - for i := 0; i < len(files); i++ { - assert.Equal(t, files[i].Name(), expectedFiles[i]) - assertIsK8sObject(t, tmpPath, files[i].Name(), expectedKinds[i]) - } -} - -func assertIsK8sObject(t *testing.T, basePath string, fileName string, gvk schema.GroupVersionKind) { - contents, err := os.ReadFile(path.Join(basePath, fileName)) - assert.NoError(t, err) - decode := scheme.Codecs.UniversalDeserializer().Decode - k8sObj, _, err := decode(contents, nil, nil) - assert.NoError(t, err) - assert.NotNil(t, k8sObj) - assert.NotEmpty(t, k8sObj.GetObjectKind().GroupVersionKind().String()) - assert.Equal(t, gvk, k8sObj.GetObjectKind().GroupVersionKind()) -} - -func Test_Handler_WorkflowService_SaveAs(t *testing.T) { - testRun := func(t *testing.T, handler WorkflowProjectHandler) { - proj, err := handler.AsObjects() - assert.NoError(t, err) - assert.NotNil(t, proj.Workflow) - - tmpPath, err := os.MkdirTemp("", "*-test") - assert.NoError(t, err) - defer os.RemoveAll(tmpPath) - - assert.NoError(t, handler.SaveAsKubernetesManifests(tmpPath)) - files, err := os.ReadDir(tmpPath) - assert.NoError(t, err) - assert.Len(t, files, 1) - - for _, f := range files { - if strings.HasSuffix(f.Name(), yamlFileExt) { - // we have only one file produced in these test cases - prefix := fmt.Sprintf("%02d-", 1) - assert.True(t, strings.HasPrefix(f.Name(), prefix)) - contents, err := os.ReadFile(path.Join(tmpPath, f.Name())) - assert.NoError(t, err) - decode := scheme.Codecs.UniversalDeserializer().Decode - k8sObj, _, err := decode(contents, nil, nil) - assert.NoError(t, err) - assert.NotNil(t, k8sObj) - assert.NotEmpty(t, k8sObj.GetObjectKind().GroupVersionKind().String()) - } - } - } - - t.Run("SaveAs in default namespace", func(t *testing.T) { - testRun(t, New("default").WithWorkflow(getWorkflowService())) - }) - - t.Run("SaveAs with empty namespace namespace", func(t *testing.T) { - testRun(t, New("").WithWorkflow(getWorkflowService())) - }) -} - -func TestWorkflowProjectHandler_Image(t *testing.T) { - handler := New("default").WithWorkflow(getWorkflowService()) - proj, err := handler.AsObjects() - handler.Image("host/namespace/service:latest") - assert.NoError(t, err) - assert.Equal(t, "host/namespace/service:latest", proj.Workflow.Spec.PodTemplate.Container.Image) -} - -func TestNormalizeEnvName(t *testing.T) { - type testCase struct { - input string - expected []string - error bool - } - tests := []testCase{ - {"my-env", []string{"MY_ENV"}, false}, - {"my.env.1", []string{"MY_ENV_1"}, false}, - {"my.env-1", []string{"MY_ENV_1"}, false}, - {"my-env.1", []string{"MY_ENV_1"}, false}, - {"my-env-1$", []string{""}, true}, - {"my-env-1&&", []string{""}, true}, - {"", []string{""}, true}, - {"$%&*", []string{""}, true}, - {"a", []string{"A"}, false}, - {"1", []string{"1"}, false}, - {"_", []string{""}, true}, - {"my env", []string{"MY_ENV"}, false}, - {" my env ", []string{"MY_ENV"}, false}, - {"-", []string{""}, true}, - {".", []string{""}, true}, - {"my-env-1234567890-long-name-with-dashes", []string{"MY_ENV_1234567890_LONG_NAME_WITH_DASHES"}, false}, - {"long-name-with-invalid-characters-@#$%^", []string{""}, true}, - {"my-env-1@name", []string{""}, true}, - {"A", []string{"A"}, false}, - {"a1_b2", []string{"A1_B2"}, false}, - {"a!!@#$b", []string{""}, true}, - {"foo.\"bar\".baz", []string{"FOO__BAR__BAZ"}, false}, - {"quarkus.'my-property'.foo", []string{"QUARKUS__MY_PROPERTY__FOO"}, false}, - {"myProperty[10]", []string{"MYPROPERTY_10"}, false}, - {"my.config[0].value", []string{"MY_CONFIG_0__VALUE"}, false}, - {"quarkus.\"myProperty\"[0].value", []string{"QUARKUS__MYPROPERTY__0__VALUE"}, false}, - {"quarkus.\"my-property\"[1].sub-name", []string{"QUARKUS__MY_PROPERTY__1__SUB_NAME"}, false}, - {"quarkus.myProperty..sub.value", []string{"QUARKUS_MYPROPERTY__SUB_VALUE"}, false}, - {"quarkus.[strange].key", []string{"QUARKUS__STRANGE__KEY"}, false}, - {"quarkus.datasource.\"datasource-name\".jdbc.url", []string{"QUARKUS_DATASOURCE__DATASOURCE_NAME__JDBC_URL"}, false}, - {"%dev.quarkus.http.port", []string{"_DEV_QUARKUS_HTTP_PORT"}, false}, - {"%staging.quarkus.http.test-port", []string{"_STAGING_QUARKUS_HTTP_TEST_PORT"}, false}, - {"%prod,dev.my.prop", []string{"_PROD_MY_PROP", "_DEV_MY_PROP"}, false}, - {"%prod,dev.quarkus.datasource.\"datasource-name\".jdbc.url", []string{"_PROD_QUARKUS_DATASOURCE__DATASOURCE_NAME__JDBC_URL", - "_DEV_QUARKUS_DATASOURCE__DATASOURCE_NAME__JDBC_URL"}, false}, - } - - for _, test := range tests { - t.Run(test.input, func(t *testing.T) { - actual, err := normalizeEnvNames(test.input) - if test.error { - assert.Error(t, err) - } else { - assert.NoError(t, err) - for index, expected := range test.expected { - assert.Equal(t, expected, actual[index]) - } - } - }) - } -} - -func getWorkflowMinimalInvalid() io.Reader { - return mustGetFile("testdata/workflows/workflow-minimal-invalid.sw.json") -} - -func getWorkflowMinimal() io.Reader { - return mustGetFile("testdata/workflows/workflow-minimal.sw.json") -} - -func getWorkflowService() io.Reader { - return mustGetFile("testdata/workflows/workflow-service.sw.json") -} - -func getWorkflowProperties() io.Reader { - return mustGetFile("testdata/workflows/application.properties") -} - -func getSpecOpenApi() io.Reader { - return mustGetFile("testdata/workflows/specs/workflow-service-openapi.json") -} - -func getSpecGeneric() io.Reader { - return mustGetFile("testdata/workflows/specs/workflow-service-schema.json") -} - -func getWorkflowSecretProperties() io.Reader { - return mustGetFile("testdata/workflows/secret.properties") -} - -func mustGetFile(filepath string) io.Reader { - file, err := os.OpenFile(filepath, os.O_RDONLY, os.ModePerm) - if err != nil { - panic(err) - } - return file -}